summaryrefslogtreecommitdiffstats
path: root/libjava/classpath/gnu/java/security/x509
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/gnu/java/security/x509')
-rw-r--r--libjava/classpath/gnu/java/security/x509/GnuPKIExtension.java59
-rw-r--r--libjava/classpath/gnu/java/security/x509/PolicyNodeImpl.java214
-rw-r--r--libjava/classpath/gnu/java/security/x509/Util.java202
-rw-r--r--libjava/classpath/gnu/java/security/x509/X500DistinguishedName.java548
-rw-r--r--libjava/classpath/gnu/java/security/x509/X509CRL.java476
-rw-r--r--libjava/classpath/gnu/java/security/x509/X509CRLEntry.java278
-rw-r--r--libjava/classpath/gnu/java/security/x509/X509CRLSelectorImpl.java138
-rw-r--r--libjava/classpath/gnu/java/security/x509/X509CertPath.java303
-rw-r--r--libjava/classpath/gnu/java/security/x509/X509CertSelectorImpl.java197
-rw-r--r--libjava/classpath/gnu/java/security/x509/X509Certificate.java745
-rw-r--r--libjava/classpath/gnu/java/security/x509/ext/AuthorityKeyIdentifier.java133
-rw-r--r--libjava/classpath/gnu/java/security/x509/ext/BasicConstraints.java129
-rw-r--r--libjava/classpath/gnu/java/security/x509/ext/CRLNumber.java97
-rw-r--r--libjava/classpath/gnu/java/security/x509/ext/CertificatePolicies.java189
-rw-r--r--libjava/classpath/gnu/java/security/x509/ext/ExtendedKeyUsage.java95
-rw-r--r--libjava/classpath/gnu/java/security/x509/ext/Extension.java289
-rw-r--r--libjava/classpath/gnu/java/security/x509/ext/GeneralNames.java155
-rw-r--r--libjava/classpath/gnu/java/security/x509/ext/IssuerAlternativeNames.java77
-rw-r--r--libjava/classpath/gnu/java/security/x509/ext/KeyUsage.java92
-rw-r--r--libjava/classpath/gnu/java/security/x509/ext/PolicyConstraint.java107
-rw-r--r--libjava/classpath/gnu/java/security/x509/ext/PolicyMappings.java104
-rw-r--r--libjava/classpath/gnu/java/security/x509/ext/PrivateKeyUsagePeriod.java105
-rw-r--r--libjava/classpath/gnu/java/security/x509/ext/ReasonCode.java85
-rw-r--r--libjava/classpath/gnu/java/security/x509/ext/SubjectAlternativeNames.java77
-rw-r--r--libjava/classpath/gnu/java/security/x509/ext/SubjectKeyIdentifier.java84
-rw-r--r--libjava/classpath/gnu/java/security/x509/ext/package.html46
-rw-r--r--libjava/classpath/gnu/java/security/x509/package.html46
27 files changed, 5070 insertions, 0 deletions
diff --git a/libjava/classpath/gnu/java/security/x509/GnuPKIExtension.java b/libjava/classpath/gnu/java/security/x509/GnuPKIExtension.java
new file mode 100644
index 00000000000..8e74b8b24ac
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/GnuPKIExtension.java
@@ -0,0 +1,59 @@
+/* GnuPKIExtension.java -- interface for GNU PKI extensions.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.x509;
+
+import gnu.java.security.OID;
+import gnu.java.security.x509.ext.Extension;
+
+import java.security.cert.X509Extension;
+import java.util.Collection;
+
+public interface GnuPKIExtension extends X509Extension
+{
+
+ /**
+ * Returns the extension object for the given object identifier.
+ *
+ * @param oid The OID of the extension to get.
+ * @return The extension, or null if there is no such extension.
+ */
+ Extension getExtension(OID oid);
+
+ Collection getExtensions();
+}
diff --git a/libjava/classpath/gnu/java/security/x509/PolicyNodeImpl.java b/libjava/classpath/gnu/java/security/x509/PolicyNodeImpl.java
new file mode 100644
index 00000000000..72cb4a9ea91
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/PolicyNodeImpl.java
@@ -0,0 +1,214 @@
+/* PolicyNodeImpl.java -- An implementation of a policy tree node.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.x509;
+
+import java.security.cert.PolicyNode;
+import java.security.cert.PolicyQualifierInfo;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+public final class PolicyNodeImpl implements PolicyNode
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private String policy;
+ private final Set expectedPolicies;
+ private final Set qualifiers;
+ private final Set children;
+ private PolicyNodeImpl parent;
+ private int depth;
+ private boolean critical;
+ private boolean readOnly;
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ public PolicyNodeImpl()
+ {
+ expectedPolicies = new HashSet();
+ qualifiers = new HashSet();
+ children = new HashSet();
+ readOnly = false;
+ critical = false;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public void addChild(PolicyNodeImpl node)
+ {
+ if (readOnly)
+ throw new IllegalStateException("read only");
+ if (node.getParent() != null)
+ throw new IllegalStateException("already a child node");
+ node.parent = this;
+ node.setDepth(depth + 1);
+ children.add(node);
+ }
+
+ public Iterator getChildren()
+ {
+ return Collections.unmodifiableSet(children).iterator();
+ }
+
+ public int getDepth()
+ {
+ return depth;
+ }
+
+ public void setDepth(int depth)
+ {
+ if (readOnly)
+ throw new IllegalStateException("read only");
+ this.depth = depth;
+ }
+
+ public void addAllExpectedPolicies(Set policies)
+ {
+ if (readOnly)
+ throw new IllegalStateException("read only");
+ expectedPolicies.addAll(policies);
+ }
+
+ public void addExpectedPolicy(String policy)
+ {
+ if (readOnly)
+ throw new IllegalStateException("read only");
+ expectedPolicies.add(policy);
+ }
+
+ public Set getExpectedPolicies()
+ {
+ return Collections.unmodifiableSet(expectedPolicies);
+ }
+
+ public PolicyNode getParent()
+ {
+ return parent;
+ }
+
+ public void addAllPolicyQualifiers (Collection qualifiers)
+ {
+ for (Iterator it = qualifiers.iterator(); it.hasNext(); )
+ {
+ if (!(it.next() instanceof PolicyQualifierInfo))
+ throw new IllegalArgumentException ("can only add PolicyQualifierInfos");
+ }
+ qualifiers.addAll (qualifiers);
+ }
+
+ public void addPolicyQualifier (PolicyQualifierInfo qualifier)
+ {
+ if (readOnly)
+ throw new IllegalStateException("read only");
+ qualifiers.add(qualifier);
+ }
+
+ public Set getPolicyQualifiers()
+ {
+ return Collections.unmodifiableSet(qualifiers);
+ }
+
+ public String getValidPolicy()
+ {
+ return policy;
+ }
+
+ public void setValidPolicy(String policy)
+ {
+ if (readOnly)
+ throw new IllegalStateException("read only");
+ this.policy = policy;
+ }
+
+ public boolean isCritical()
+ {
+ return critical;
+ }
+
+ public void setCritical(boolean critical)
+ {
+ if (readOnly)
+ throw new IllegalStateException("read only");
+ this.critical = critical;
+ }
+
+ public void setReadOnly()
+ {
+ if (readOnly)
+ return;
+ readOnly = true;
+ for (Iterator it = getChildren(); it.hasNext(); )
+ ((PolicyNodeImpl) it.next()).setReadOnly();
+ }
+
+ public String toString()
+ {
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < depth; i++)
+ buf.append(" ");
+ buf.append("(");
+ buf.append(PolicyNodeImpl.class.getName());
+ buf.append(" (oid ");
+ buf.append(policy);
+ buf.append(") (depth ");
+ buf.append(depth);
+ buf.append(") (qualifiers ");
+ buf.append(qualifiers);
+ buf.append(") (critical ");
+ buf.append(critical);
+ buf.append(") (expectedPolicies ");
+ buf.append(expectedPolicies);
+ buf.append(") (children (");
+ final String nl = System.getProperty("line.separator");
+ for (Iterator it = getChildren(); it.hasNext(); )
+ {
+ buf.append(nl);
+ buf.append(it.next().toString());
+ }
+ buf.append(")))");
+ return buf.toString();
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/x509/Util.java b/libjava/classpath/gnu/java/security/x509/Util.java
new file mode 100644
index 00000000000..d27392026f8
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/Util.java
@@ -0,0 +1,202 @@
+/* Util.java -- Miscellaneous utility methods.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.x509;
+
+/**
+ * A collection of useful class methods.
+ *
+ * @author Casey Marshall (rsdio@metastatic.org)
+ */
+public final class Util
+{
+
+ // Constants.
+ // -------------------------------------------------------------------------
+
+ public static final String HEX = "0123456789abcdef";
+
+ // Class methods.
+ // -------------------------------------------------------------------------
+
+ /**
+ * Convert a byte array to a hexadecimal string, as though it were a
+ * big-endian arbitrarily-sized integer.
+ *
+ * @param buf The bytes to format.
+ * @param off The offset to start at.
+ * @param len The number of bytes to format.
+ * @return A hexadecimal representation of the specified bytes.
+ */
+ public static String toHexString(byte[] buf, int off, int len)
+ {
+ StringBuffer str = new StringBuffer();
+ for (int i = 0; i < len; i++)
+ {
+ str.append(HEX.charAt(buf[i+off] >>> 4 & 0x0F));
+ str.append(HEX.charAt(buf[i+off] & 0x0F));
+ }
+ return str.toString();
+ }
+
+ /**
+ * See {@link #toHexString(byte[],int,int)}.
+ */
+ public static String toHexString(byte[] buf)
+ {
+ return Util.toHexString(buf, 0, buf.length);
+ }
+
+ /**
+ * Convert a byte array to a hexadecimal string, separating octets
+ * with the given character.
+ *
+ * @param buf The bytes to format.
+ * @param off The offset to start at.
+ * @param len The number of bytes to format.
+ * @param sep The character to insert between octets.
+ * @return A hexadecimal representation of the specified bytes.
+ */
+ public static String toHexString(byte[] buf, int off, int len, char sep)
+ {
+ StringBuffer str = new StringBuffer();
+ for (int i = 0; i < len; i++)
+ {
+ str.append(HEX.charAt(buf[i+off] >>> 4 & 0x0F));
+ str.append(HEX.charAt(buf[i+off] & 0x0F));
+ if (i < len - 1)
+ str.append(sep);
+ }
+ return str.toString();
+ }
+
+ /**
+ * See {@link #toHexString(byte[],int,int,char)}.
+ */
+ public static String toHexString(byte[] buf, char sep)
+ {
+ return Util.toHexString(buf, 0, buf.length, sep);
+ }
+
+ /**
+ * Create a representation of the given byte array similar to the
+ * output of `hexdump -C', which is
+ *
+ * <p><pre>OFFSET SIXTEEN-BYTES-IN-HEX PRINTABLE-BYTES</pre>
+ *
+ * <p>The printable bytes show up as-is if they are printable and
+ * not a newline character, otherwise showing as '.'.
+ *
+ * @param buf The bytes to format.
+ * @param off The offset to start at.
+ * @param len The number of bytes to encode.
+ * @return The formatted string.
+ */
+ public static String hexDump(byte[] buf, int off, int len, String prefix)
+ {
+ String nl = System.getProperty("line.separator");
+ StringBuffer str = new StringBuffer();
+ int i = 0;
+ while (i < len)
+ {
+ str.append(prefix);
+ str.append(Util.formatInt(i+off, 16, 8));
+ str.append(" ");
+ String s = Util.toHexString(buf, i+off, Math.min(16, len-i), ' ');
+ str.append(s);
+ for (int j = 56 - (56 - s.length()); j < 56; j++)
+ str.append(" ");
+ for (int j = 0; j < Math.min(16, len - i); j++)
+ {
+ if ((buf[i+off+j] & 0xFF) < 0x20 || (buf[i+off+j] & 0xFF) > 0x7E)
+ str.append('.');
+ else
+ str.append((char) (buf[i+off+j] & 0xFF));
+ }
+ str.append(nl);
+ i += 16;
+ }
+ return str.toString();
+ }
+
+ /**
+ * See {@link #hexDump(byte[],int,int)}.
+ */
+ public static String hexDump(byte[] buf, String prefix)
+ {
+ return hexDump(buf, 0, buf.length, prefix);
+ }
+
+ /**
+ * Format an integer into the specified radix, zero-filled.
+ *
+ * @param i The integer to format.
+ * @param radix The radix to encode to.
+ * @param len The target length of the string. The string is
+ * zero-padded to this length, but may be longer.
+ * @return The formatted integer.
+ */
+ public static String formatInt(int i, int radix, int len)
+ {
+ String s = Integer.toString(i, radix);
+ StringBuffer buf = new StringBuffer();
+ for (int j = 0; j < len - s.length(); j++)
+ buf.append("0");
+ buf.append(s);
+ return buf.toString();
+ }
+
+ /**
+ * Convert a hexadecimal string into its byte representation.
+ *
+ * @param hex The hexadecimal string.
+ * @return The converted bytes.
+ */
+ public static byte[] toByteArray(String hex)
+ {
+ hex = hex.toLowerCase();
+ byte[] buf = new byte[hex.length() / 2];
+ int j = 0;
+ for (int i = 0; i < buf.length; i++)
+ {
+ buf[i] = (byte) ((Character.digit(hex.charAt(j++), 16) << 4) |
+ Character.digit(hex.charAt(j++), 16));
+ }
+ return buf;
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/x509/X500DistinguishedName.java b/libjava/classpath/gnu/java/security/x509/X500DistinguishedName.java
new file mode 100644
index 00000000000..daf746f5dc5
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/X500DistinguishedName.java
@@ -0,0 +1,548 @@
+/* X500DistinguishedName.java -- X.500 distinguished name.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.x509;
+
+import gnu.java.security.OID;
+import gnu.java.security.der.DER;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class X500DistinguishedName implements Principal
+{
+
+ // Constants and fields.
+ // -------------------------------------------------------------------------
+
+ public static final OID CN = new OID("2.5.4.3");
+ public static final OID C = new OID("2.5.4.6");
+ public static final OID L = new OID("2.5.4.7");
+ public static final OID ST = new OID("2.5.4.8");
+ public static final OID STREET = new OID("2.5.4.9");
+ public static final OID O = new OID("2.5.4.10");
+ public static final OID OU = new OID("2.5.4.11");
+ public static final OID T = new OID("2.5.4.12");
+ public static final OID DNQ = new OID("2.5.4.46");
+ public static final OID NAME = new OID("2.5.4.41");
+ public static final OID GIVENNAME = new OID("2.5.4.42");
+ public static final OID INITIALS = new OID("2.5.4.43");
+ public static final OID GENERATION = new OID("2.5.4.44");
+ public static final OID EMAIL = new OID("1.2.840.113549.1.9.1");
+ public static final OID DC = new OID("0.9.2342.19200300.100.1.25");
+ public static final OID UID = new OID("0.9.2342.19200300.100.1.1");
+
+ private List components;
+ private Map currentRdn;
+ private boolean fixed;
+ private String stringRep;
+ private byte[] encoded;
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ public X500DistinguishedName()
+ {
+ components = new LinkedList();
+ currentRdn = new LinkedHashMap();
+ components.add(currentRdn);
+ }
+
+ public X500DistinguishedName(String name)
+ {
+ this();
+ try
+ {
+ parseString(name);
+ }
+ catch (IOException ioe)
+ {
+ throw new IllegalArgumentException(ioe.toString());
+ }
+ }
+
+ public X500DistinguishedName(byte[] encoded) throws IOException
+ {
+ this();
+ parseDer(new DERReader(encoded));
+ }
+
+ public X500DistinguishedName(InputStream encoded) throws IOException
+ {
+ this();
+ parseDer(new DERReader(encoded));
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public String getName()
+ {
+ return toString();
+ }
+
+ public void newRelativeDistinguishedName()
+ {
+ if (fixed || currentRdn.isEmpty()) return;
+ currentRdn = new LinkedHashMap();
+ components.add(currentRdn);
+ }
+
+ public int size()
+ {
+ return components.size();
+ }
+
+ public int countComponents()
+ {
+ int count = 0;
+ for (Iterator it = components.iterator(); it.hasNext(); )
+ {
+ count += ((Map) it.next()).size();
+ }
+ return count;
+ }
+
+ public boolean containsComponent(OID oid, String value)
+ {
+ for (Iterator it = components.iterator(); it.hasNext(); )
+ {
+ Map rdn = (Map) it.next();
+ String s = (String) rdn.get(oid);
+ if (s == null)
+ continue;
+ if (compressWS(value).equalsIgnoreCase(compressWS(s)))
+ return true;
+ }
+ return false;
+ }
+
+ public String getComponent(OID oid)
+ {
+ for (Iterator it = components.iterator(); it.hasNext(); )
+ {
+ Map rdn = (Map) it.next();
+ if (rdn.containsKey(oid))
+ return (String) rdn.get(oid);
+ }
+ return null;
+ }
+
+ public String getComponent(OID oid, int rdn)
+ {
+ if (rdn >= size())
+ return null;
+ return (String) ((Map) components.get(rdn)).get(oid);
+ }
+
+ public void putComponent(OID oid, String value)
+ {
+ currentRdn.put(oid, value);
+ }
+
+ public void putComponent(String name, String value)
+ {
+ name = name.trim().toLowerCase();
+ if (name.equals("cn"))
+ putComponent(CN, value);
+ else if (name.equals("c"))
+ putComponent(C, value);
+ else if (name.equals("l"))
+ putComponent(L, value);
+ else if (name.equals("street"))
+ putComponent(STREET, value);
+ else if (name.equals("st"))
+ putComponent(ST, value);
+ else if (name.equals("t"))
+ putComponent(T, value);
+ else if (name.equals("dnq"))
+ putComponent(DNQ, value);
+ else if (name.equals("name"))
+ putComponent(NAME, value);
+ else if (name.equals("givenname"))
+ putComponent(GIVENNAME, value);
+ else if (name.equals("initials"))
+ putComponent(INITIALS, value);
+ else if (name.equals("generation"))
+ putComponent(GENERATION, value);
+ else if (name.equals("email"))
+ putComponent(EMAIL, value);
+ else if (name.equals("dc"))
+ putComponent(DC, value);
+ else if (name.equals("uid"))
+ putComponent(UID, value);
+ else
+ putComponent(new OID(name), value);
+ }
+
+ public void setUnmodifiable()
+ {
+ if (fixed) return;
+ fixed = true;
+ List newComps = new ArrayList(components.size());
+ for (Iterator it = components.iterator(); it.hasNext(); )
+ {
+ Map rdn = (Map) it.next();
+ rdn = Collections.unmodifiableMap(rdn);
+ newComps.add(rdn);
+ }
+ components = Collections.unmodifiableList(newComps);
+ currentRdn = Collections.EMPTY_MAP;
+ }
+
+ public int hashCode()
+ {
+ int sum = 0;
+ for (Iterator it = components.iterator(); it.hasNext(); )
+ {
+ Map m = (Map) it.next();
+ for (Iterator it2 = m.entrySet().iterator(); it2.hasNext(); )
+ {
+ Map.Entry e = (Map.Entry) it2.next();
+ sum += e.getKey().hashCode();
+ sum += e.getValue().hashCode();
+ }
+ }
+ return sum;
+ }
+
+ public boolean equals(Object o)
+ {
+ if (!(o instanceof X500DistinguishedName))
+ return false;
+ if (size() != ((X500DistinguishedName) o).size())
+ return false;
+ for (int i = 0; i < size(); i++)
+ {
+ Map m = (Map) components.get(i);
+ for (Iterator it2 = m.entrySet().iterator(); it2.hasNext(); )
+ {
+ Map.Entry e = (Map.Entry) it2.next();
+ OID oid = (OID) e.getKey();
+ String v1 = (String) e.getValue();
+ String v2 = ((X500DistinguishedName) o).getComponent(oid, i);
+ if (!compressWS(v1).equalsIgnoreCase(compressWS(v2)))
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public String toString()
+ {
+ if (fixed && stringRep != null)
+ return stringRep;
+ StringBuffer str = new StringBuffer();
+ for (Iterator it = components.iterator(); it.hasNext(); )
+ {
+ Map m = (Map) it.next();
+ for (Iterator it2 = m.entrySet().iterator(); it2.hasNext(); )
+ {
+ Map.Entry entry = (Map.Entry) it2.next();
+ OID oid = (OID) entry.getKey();
+ String value = (String) entry.getValue();
+ if (oid.equals(CN))
+ str.append("CN");
+ else if (oid.equals(C))
+ str.append("C");
+ else if (oid.equals(L))
+ str.append("L");
+ else if (oid.equals(ST))
+ str.append("ST");
+ else if (oid.equals(STREET))
+ str.append("STREET");
+ else if (oid.equals(O))
+ str.append("O");
+ else if (oid.equals(OU))
+ str.append("OU");
+ else if (oid.equals(T))
+ str.append("T");
+ else if (oid.equals(DNQ))
+ str.append("DNQ");
+ else if (oid.equals(NAME))
+ str.append("NAME");
+ else
+ str.append(oid.toString());
+ str.append('=');
+ str.append(value);
+ if (it2.hasNext())
+ str.append("+");
+ }
+ if (it.hasNext())
+ str.append(',');
+ }
+ return (stringRep = str.toString());
+ }
+
+ public byte[] getDer()
+ {
+ if (fixed && encoded != null)
+ return (byte[]) encoded.clone();
+ ArrayList name = new ArrayList(components.size());
+ for (Iterator it = components.iterator(); it.hasNext(); )
+ {
+ Map m = (Map) it.next();
+ if (m.isEmpty())
+ continue;
+ Set rdn = new HashSet();
+ for (Iterator it2 = m.entrySet().iterator(); it2.hasNext(); )
+ {
+ Map.Entry e = (Map.Entry) it.next();
+ ArrayList atav = new ArrayList(2);
+ atav.add(new DERValue(DER.OBJECT_IDENTIFIER, e.getKey()));
+ atav.add(new DERValue(DER.UTF8_STRING, e.getValue()));
+ rdn.add(new DERValue(DER.SEQUENCE|DER.CONSTRUCTED, atav));
+ }
+ name.add(new DERValue(DER.SET|DER.CONSTRUCTED, rdn));
+ }
+ DERValue val = new DERValue(DER.SEQUENCE|DER.CONSTRUCTED, name);
+ return (byte[]) (encoded = val.getEncoded()).clone();
+ }
+
+ // Own methods.
+ // -------------------------------------------------------------------------
+
+ private int sep;
+
+ private void parseString(String str) throws IOException
+ {
+ Reader in = new StringReader(str);
+ while (true)
+ {
+ String key = readAttributeType(in);
+ if (key == null)
+ break;
+ String value = readAttributeValue(in);
+ putComponent(key, value);
+ if (sep == ',')
+ newRelativeDistinguishedName();
+ }
+ setUnmodifiable();
+ }
+
+ private String readAttributeType(Reader in) throws IOException
+ {
+ StringBuffer buf = new StringBuffer();
+ int ch;
+ while ((ch = in.read()) != '=')
+ {
+ if (ch == -1)
+ {
+ if (buf.length() > 0)
+ throw new EOFException();
+ return null;
+ }
+ if (ch > 127)
+ throw new IOException("Invalid char: " + (char) ch);
+ if (Character.isLetterOrDigit((char) ch) || ch == '-' || ch == '.')
+ buf.append((char) ch);
+ else
+ throw new IOException("Invalid char: " + (char) ch);
+ }
+ return buf.toString();
+ }
+
+ private String readAttributeValue(Reader in) throws IOException
+ {
+ StringBuffer buf = new StringBuffer();
+ int ch = in.read();
+ if (ch == '#')
+ {
+ while (true)
+ {
+ ch = in.read();
+ if (('a' <= ch && ch <= 'f') || ('A' <= ch && ch <= 'F')
+ || Character.isDigit((char) ch))
+ buf.append((char) ch);
+ else if (ch == '+' || ch == ',')
+ {
+ sep = ch;
+ String hex = buf.toString();
+ return new String(Util.toByteArray(hex));
+ }
+ else
+ throw new IOException("illegal character: " + (char) ch);
+ }
+ }
+ else if (ch == '"')
+ {
+ while (true)
+ {
+ ch = in.read();
+ if (ch == '"')
+ break;
+ else if (ch == '\\')
+ {
+ ch = in.read();
+ if (ch == -1)
+ throw new EOFException();
+ if (('a' <= ch && ch <= 'f') || ('A' <= ch && ch <= 'F')
+ || Character.isDigit((char) ch))
+ {
+ int i = Character.digit((char) ch, 16) << 4;
+ ch = in.read();
+ if (!(('a' <= ch && ch <= 'f') || ('A' <= ch && ch <= 'F')
+ || Character.isDigit((char) ch)))
+ throw new IOException("illegal hex char");
+ i |= Character.digit((char) ch, 16);
+ buf.append((char) i);
+ }
+ else
+ buf.append((char) ch);
+ }
+ else
+ buf.append((char) ch);
+ }
+ sep = in.read();
+ if (sep != '+' || sep != ',')
+ throw new IOException("illegal character: " + (char) ch);
+ return buf.toString();
+ }
+ else
+ {
+ while (true)
+ {
+ switch (ch)
+ {
+ case '+':
+ case ',':
+ sep = ch;
+ return buf.toString();
+ case '\\':
+ ch = in.read();
+ if (ch == -1)
+ throw new EOFException();
+ if (('a' <= ch && ch <= 'f') || ('A' <= ch && ch <= 'F')
+ || Character.isDigit((char) ch))
+ {
+ int i = Character.digit((char) ch, 16) << 4;
+ ch = in.read();
+ if (!(('a' <= ch && ch <= 'f') || ('A' <= ch && ch <= 'F')
+ || Character.isDigit((char) ch)))
+ throw new IOException("illegal hex char");
+ i |= Character.digit((char) ch, 16);
+ buf.append((char) i);
+ }
+ else
+ buf.append((char) ch);
+ break;
+ case '=':
+ case '<':
+ case '>':
+ case '#':
+ case ';':
+ throw new IOException("illegal character: " + (char) ch);
+ case -1:
+ throw new EOFException();
+ default:
+ buf.append((char) ch);
+ }
+ }
+ }
+ }
+
+ private void parseDer(DERReader der) throws IOException
+ {
+ DERValue name = der.read();
+ if (!name.isConstructed())
+ throw new IOException("malformed Name");
+ encoded = name.getEncoded();
+ int len = 0;
+ while (len < name.getLength())
+ {
+ DERValue rdn = der.read();
+ if (!rdn.isConstructed())
+ throw new IOException("badly formed RDNSequence");
+ int len2 = 0;
+ while (len2 < rdn.getLength())
+ {
+ DERValue atav = der.read();
+ if (!atav.isConstructed())
+ throw new IOException("badly formed AttributeTypeAndValue");
+ DERValue val = der.read();
+ if (val.getTag() != DER.OBJECT_IDENTIFIER)
+ throw new IOException("badly formed AttributeTypeAndValue");
+ OID oid = (OID) val.getValue();
+ val = der.read();
+ if (!(val.getValue() instanceof String))
+ throw new IOException("badly formed AttributeTypeAndValue");
+ String value = (String) val.getValue();
+ putComponent(oid, value);
+ len2 += atav.getEncodedLength();
+ }
+ len += rdn.getEncodedLength();
+ if (len < name.getLength())
+ newRelativeDistinguishedName();
+ }
+ setUnmodifiable();
+ }
+
+ private static String compressWS(String str)
+ {
+ StringBuffer buf = new StringBuffer();
+ char lastChar = 0;
+ for (int i = 0; i < str.length(); i++)
+ {
+ char c = str.charAt(i);
+ if (Character.isWhitespace(c))
+ {
+ if (!Character.isWhitespace(lastChar))
+ buf.append(' ');
+ }
+ else
+ buf.append(c);
+ lastChar = c;
+ }
+ return buf.toString().trim();
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/x509/X509CRL.java b/libjava/classpath/gnu/java/security/x509/X509CRL.java
new file mode 100644
index 00000000000..5b2d3b14130
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/X509CRL.java
@@ -0,0 +1,476 @@
+/* X509CRL.java -- X.509 certificate revocation list.
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.x509;
+
+import gnu.java.security.OID;
+import gnu.java.security.der.BitString;
+import gnu.java.security.der.DER;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+import gnu.java.security.x509.ext.Extension;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Principal;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.cert.CRLException;
+import java.security.cert.Certificate;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.security.auth.x500.X500Principal;
+
+/**
+ * X.509 certificate revocation lists.
+ *
+ * @author Casey Marshall (rsdio@metastatic.org)
+ */
+public class X509CRL extends java.security.cert.X509CRL
+ implements GnuPKIExtension
+{
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ private static final boolean DEBUG = false;
+ private static void debug(String msg)
+ {
+ if (DEBUG)
+ {
+ System.err.print(">> X509CRL: ");
+ System.err.println(msg);
+ }
+ }
+
+ private static final OID ID_DSA = new OID("1.2.840.10040.4.1");
+ private static final OID ID_DSA_WITH_SHA1 = new OID("1.2.840.10040.4.3");
+ private static final OID ID_RSA = new OID("1.2.840.113549.1.1.1");
+ private static final OID ID_RSA_WITH_MD2 = new OID("1.2.840.113549.1.1.2");
+ private static final OID ID_RSA_WITH_MD5 = new OID("1.2.840.113549.1.1.4");
+ private static final OID ID_RSA_WITH_SHA1 = new OID("1.2.840.113549.1.1.5");
+
+ private byte[] encoded;
+
+ private byte[] tbsCRLBytes;
+ private int version;
+ private OID algId;
+ private byte[] algParams;
+ private Date thisUpdate;
+ private Date nextUpdate;
+ private X500DistinguishedName issuerDN;
+ private HashMap revokedCerts;
+ private HashMap extensions;
+
+ private OID sigAlg;
+ private byte[] sigAlgParams;
+ private byte[] rawSig;
+ private byte[] signature;
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Create a new X.509 CRL.
+ *
+ * @param encoded The DER encoded CRL.
+ * @throws CRLException If the input bytes are incorrect.
+ * @throws IOException If the input bytes cannot be read.
+ */
+ public X509CRL(InputStream encoded) throws CRLException, IOException
+ {
+ super();
+ revokedCerts = new HashMap();
+ extensions = new HashMap();
+ try
+ {
+ parse(encoded);
+ }
+ catch (IOException ioe)
+ {
+ ioe.printStackTrace();
+ throw ioe;
+ }
+ catch (Exception x)
+ {
+ x.printStackTrace();
+ throw new CRLException(x.toString());
+ }
+ }
+
+ // X509CRL methods.
+ // ------------------------------------------------------------------------
+
+ public boolean equals(Object o)
+ {
+ if (!(o instanceof X509CRL))
+ return false;
+ return ((X509CRL) o).getRevokedCertificates().equals(revokedCerts.values());
+ }
+
+ public int hashCode()
+ {
+ return revokedCerts.hashCode();
+ }
+
+ public byte[] getEncoded() throws CRLException
+ {
+ return (byte[]) encoded.clone();
+ }
+
+ public void verify(PublicKey key)
+ throws CRLException, NoSuchAlgorithmException, InvalidKeyException,
+ NoSuchProviderException, SignatureException
+ {
+ Signature sig = Signature.getInstance(sigAlg.toString());
+ doVerify(sig, key);
+ }
+
+ public void verify(PublicKey key, String provider)
+ throws CRLException, NoSuchAlgorithmException, InvalidKeyException,
+ NoSuchProviderException, SignatureException
+ {
+ Signature sig = Signature.getInstance(sigAlg.toString(), provider);
+ doVerify(sig, key);
+ }
+
+ public int getVersion()
+ {
+ return version;
+ }
+
+ public Principal getIssuerDN()
+ {
+ return issuerDN;
+ }
+
+ public X500Principal getIssuerX500Principal()
+ {
+ return new X500Principal(issuerDN.getDer());
+ }
+
+ public Date getThisUpdate()
+ {
+ return (Date) thisUpdate.clone();
+ }
+
+ public Date getNextUpdate()
+ {
+ if (nextUpdate != null)
+ return (Date) nextUpdate.clone();
+ return null;
+ }
+
+ public java.security.cert.X509CRLEntry getRevokedCertificate(BigInteger serialNo)
+ {
+ return (java.security.cert.X509CRLEntry) revokedCerts.get(serialNo);
+ }
+
+ public Set getRevokedCertificates()
+ {
+ return Collections.unmodifiableSet(new HashSet(revokedCerts.values()));
+ }
+
+ public byte[] getTBSCertList() throws CRLException
+ {
+ return (byte[]) tbsCRLBytes.clone();
+ }
+
+ public byte[] getSignature()
+ {
+ return (byte[]) rawSig.clone();
+ }
+
+ public String getSigAlgName()
+ {
+ if (sigAlg.equals(ID_DSA_WITH_SHA1))
+ return "SHA1withDSA";
+ if (sigAlg.equals(ID_RSA_WITH_MD2))
+ return "MD2withRSA";
+ if (sigAlg.equals(ID_RSA_WITH_MD5))
+ return "MD5withRSA";
+ if (sigAlg.equals(ID_RSA_WITH_SHA1))
+ return "SHA1withRSA";
+ return "unknown";
+ }
+
+ public String getSigAlgOID()
+ {
+ return sigAlg.toString();
+ }
+
+ public byte[] getSigAlgParams()
+ {
+ if (sigAlgParams != null)
+ return (byte[]) sigAlgParams.clone();
+ return null;
+ }
+
+ // X509Extension methods.
+ // ------------------------------------------------------------------------
+
+ public boolean hasUnsupportedCriticalExtension()
+ {
+ for (Iterator it = extensions.values().iterator(); it.hasNext(); )
+ {
+ Extension e = (Extension) it.next();
+ if (e.isCritical() && !e.isSupported())
+ return true;
+ }
+ return false;
+ }
+
+ public Set getCriticalExtensionOIDs()
+ {
+ HashSet s = new HashSet();
+ for (Iterator it = extensions.values().iterator(); it.hasNext(); )
+ {
+ Extension e = (Extension) it.next();
+ if (e.isCritical())
+ s.add(e.getOid().toString());
+ }
+ return Collections.unmodifiableSet(s);
+ }
+
+ public Set getNonCriticalExtensionOIDs()
+ {
+ HashSet s = new HashSet();
+ for (Iterator it = extensions.values().iterator(); it.hasNext(); )
+ {
+ Extension e = (Extension) it.next();
+ if (!e.isCritical())
+ s.add(e.getOid().toString());
+ }
+ return Collections.unmodifiableSet(s);
+ }
+
+ public byte[] getExtensionValue(String oid)
+ {
+ Extension e = getExtension(new OID(oid));
+ if (e != null)
+ {
+ return e.getValue().getEncoded();
+ }
+ return null;
+ }
+
+ // GnuPKIExtension method.
+ // -------------------------------------------------------------------------
+
+ public Extension getExtension(OID oid)
+ {
+ return (Extension) extensions.get(oid);
+ }
+
+ public Collection getExtensions()
+ {
+ return extensions.values();
+ }
+
+ // CRL methods.
+ // -------------------------------------------------------------------------
+
+ public String toString()
+ {
+ return X509CRL.class.getName();
+ }
+
+ public boolean isRevoked(Certificate cert)
+ {
+ if (!(cert instanceof java.security.cert.X509Certificate))
+ throw new IllegalArgumentException("not a X.509 certificate");
+ BigInteger certSerial =
+ ((java.security.cert.X509Certificate) cert).getSerialNumber();
+ X509CRLEntry ent = (X509CRLEntry) revokedCerts.get(certSerial);
+ if (ent == null)
+ return false;
+ return ent.getRevocationDate().compareTo(new Date()) < 0;
+ }
+
+ // Own methods.
+ // ------------------------------------------------------------------------
+
+ private void doVerify(Signature sig, PublicKey key)
+ throws CRLException, InvalidKeyException, SignatureException
+ {
+ sig.initVerify(key);
+ sig.update(tbsCRLBytes);
+ if (!sig.verify(signature))
+ throw new CRLException("signature not verified");
+ }
+
+ private void parse(InputStream in) throws Exception
+ {
+ // CertificateList ::= SEQUENCE {
+ DERReader der = new DERReader(in);
+ DERValue val = der.read();
+ debug("start CertificateList len == " + val.getLength());
+ if (!val.isConstructed())
+ throw new IOException("malformed CertificateList");
+ encoded = val.getEncoded();
+
+ // tbsCertList ::= SEQUENCE { -- TBSCertList
+ val = der.read();
+ if (!val.isConstructed())
+ throw new IOException("malformed TBSCertList");
+ debug("start tbsCertList len == " + val.getLength());
+ tbsCRLBytes = val.getEncoded();
+
+ // version Version OPTIONAL,
+ // -- If present must be v2
+ val = der.read();
+ if (val.getValue() instanceof BigInteger)
+ {
+ version = ((BigInteger) val.getValue()).intValue() + 1;
+ val = der.read();
+ }
+ else
+ version = 1;
+ debug("read version == " + version);
+
+ // signature AlgorithmIdentifier,
+ debug("start AlgorithmIdentifier len == " + val.getLength());
+ if (!val.isConstructed())
+ throw new IOException("malformed AlgorithmIdentifier");
+ DERValue algIdVal = der.read();
+ algId = (OID) algIdVal.getValue();
+ debug("read object identifier == " + algId);
+ if (val.getLength() > algIdVal.getEncodedLength())
+ {
+ val = der.read();
+ debug("read parameters len == " + val.getEncodedLength());
+ algParams = val.getEncoded();
+ if (val.isConstructed())
+ in.skip(val.getLength());
+ }
+
+ // issuer Name,
+ val = der.read();
+ issuerDN = new X500DistinguishedName(val.getEncoded());
+ der.skip(val.getLength());
+ debug("read issuer == " + issuerDN);
+
+ // thisUpdate Time,
+ thisUpdate = (Date) der.read().getValue();
+ debug("read thisUpdate == " + thisUpdate);
+
+ // nextUpdate Time OPTIONAL,
+ val = der.read();
+ if (val.getValue() instanceof Date)
+ {
+ nextUpdate = (Date) val.getValue();
+ debug("read nextUpdate == " + nextUpdate);
+ val = der.read();
+ }
+
+ // revokedCertificates SEQUENCE OF SEQUENCE {
+ // -- X509CRLEntry objects...
+ // } OPTIONAL,
+ if (val.getTag() != 0)
+ {
+ int len = 0;
+ while (len < val.getLength())
+ {
+ X509CRLEntry entry = new X509CRLEntry(version, der);
+ revokedCerts.put(entry.getSerialNumber(), entry);
+ len += entry.getEncoded().length;
+ }
+ val = der.read();
+ }
+
+ // crlExtensions [0] EXPLICIT Extensions OPTIONAL
+ // -- if present MUST be v2
+ if (val.getTagClass() != DER.UNIVERSAL && val.getTag() == 0)
+ {
+ if (version < 2)
+ throw new IOException("extra data in CRL");
+ DERValue exts = der.read();
+ if (!exts.isConstructed())
+ throw new IOException("malformed Extensions");
+ debug("start Extensions len == " + exts.getLength());
+ int len = 0;
+ while (len < exts.getLength())
+ {
+ DERValue ext = der.read();
+ if (!ext.isConstructed())
+ throw new IOException("malformed Extension");
+ Extension e = new Extension(ext.getEncoded());
+ extensions.put(e.getOid(), e);
+ der.skip(ext.getLength());
+ len += ext.getEncodedLength();
+ debug("current count == " + len);
+ }
+ val = der.read();
+ }
+
+ debug("read tag == " + val.getTag());
+ if (!val.isConstructed())
+ throw new IOException("malformed AlgorithmIdentifier");
+ debug("start AlgorithmIdentifier len == " + val.getLength());
+ DERValue sigAlgVal = der.read();
+ debug("read tag == " + sigAlgVal.getTag());
+ if (sigAlgVal.getTag() != DER.OBJECT_IDENTIFIER)
+ throw new IOException("malformed AlgorithmIdentifier");
+ sigAlg = (OID) sigAlgVal.getValue();
+ debug("signature id == " + sigAlg);
+ debug("sigAlgVal length == " + sigAlgVal.getEncodedLength());
+ if (val.getLength() > sigAlgVal.getEncodedLength())
+ {
+ val = der.read();
+ debug("sig params tag = " + val.getTag() + " len == " + val.getEncodedLength());
+ sigAlgParams = (byte[]) val.getEncoded();
+ if (val.isConstructed())
+ in.skip(val.getLength());
+ }
+ val = der.read();
+ debug("read tag = " + val.getTag());
+ rawSig = val.getEncoded();
+ signature = ((BitString) val.getValue()).toByteArray();
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/x509/X509CRLEntry.java b/libjava/classpath/gnu/java/security/x509/X509CRLEntry.java
new file mode 100644
index 00000000000..a3bcfdea823
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/X509CRLEntry.java
@@ -0,0 +1,278 @@
+/* X509CRLEntry.java -- an entry in a X.509 CRL.
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.x509;
+
+import gnu.java.security.OID;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+import gnu.java.security.x509.ext.Extension;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.cert.CRLException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * A single entry in a X.509 certificate revocation list.
+ *
+ * @see X509CRL
+ * @author Casey Marshall
+ */
+class X509CRLEntry extends java.security.cert.X509CRLEntry
+ implements GnuPKIExtension
+{
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ private static final boolean DEBUG = false;
+ private static void debug(String msg)
+ {
+ if (DEBUG)
+ {
+ System.err.print(">> X509CRLEntry: ");
+ System.err.println(msg);
+ }
+ }
+
+ /** The DER encoded form of this CRL entry. */
+ private byte[] encoded;
+
+ /** The revoked certificate's serial number. */
+ private BigInteger serialNo;
+
+ /** The date the certificate was revoked. */
+ private Date revocationDate;
+
+ /** The CRL entry extensions. */
+ private HashMap extensions;
+
+ // Constructor.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Create a new X.509 certificate revocation list entry from the given
+ * input stream and CRL version number.
+ *
+ * @param version The CRL version.
+ * @param encoded The stream of DER bytes.
+ * @throws CRLException If the ASN.1 structure is invalid.
+ * @throws IOException If the bytes cannot be read.
+ */
+ X509CRLEntry(int version, DERReader encoded)
+ throws CRLException, IOException
+ {
+ super();
+ extensions = new HashMap();
+ try
+ {
+ parse(version, encoded);
+ }
+ catch (IOException ioe)
+ {
+ throw ioe;
+ }
+ catch (Exception x)
+ {
+ throw new CRLException(x.toString());
+ }
+ }
+
+ // X509CRLEntry methods.
+ // ------------------------------------------------------------------------
+
+ public boolean equals(Object o)
+ {
+ if (!(o instanceof X509CRLEntry))
+ return false;
+ return ((X509CRLEntry) o).getSerialNumber().equals(serialNo) &&
+ ((X509CRLEntry) o).getRevocationDate().equals(revocationDate);
+ }
+
+ public int hashCode()
+ {
+ return serialNo.hashCode();
+ }
+
+ public byte[] getEncoded() throws CRLException
+ {
+ return (byte[]) encoded.clone();
+ }
+
+ public BigInteger getSerialNumber()
+ {
+ return serialNo;
+ }
+
+ public Date getRevocationDate()
+ {
+ return (Date) revocationDate.clone();
+ }
+
+ public boolean hasExtensions()
+ {
+ return ! extensions.isEmpty();
+ }
+
+ public String toString()
+ {
+ return "X509CRLEntry serial=" + serialNo + " revocation date="
+ + revocationDate + " ext=" + extensions;
+ }
+
+ // X509Extension methods.
+ // -------------------------------------------------------------------------
+
+ public boolean hasUnsupportedCriticalExtension()
+ {
+ for (Iterator it = extensions.values().iterator(); it.hasNext(); )
+ {
+ Extension e = (Extension) it.next();
+ if (e.isCritical() && !e.isSupported())
+ return true;
+ }
+ return false;
+ }
+
+ public Set getCriticalExtensionOIDs()
+ {
+ HashSet s = new HashSet();
+ for (Iterator it = extensions.values().iterator(); it.hasNext(); )
+ {
+ Extension e = (Extension) it.next();
+ if (e.isCritical())
+ s.add(e.getOid().toString());
+ }
+ return Collections.unmodifiableSet(s);
+ }
+
+ public Set getNonCriticalExtensionOIDs()
+ {
+ HashSet s = new HashSet();
+ for (Iterator it = extensions.values().iterator(); it.hasNext(); )
+ {
+ Extension e = (Extension) it.next();
+ if (!e.isCritical())
+ s.add(e.getOid().toString());
+ }
+ return Collections.unmodifiableSet(s);
+ }
+
+ public byte[] getExtensionValue(String oid)
+ {
+ Extension e = getExtension(new OID(oid));
+ if (e != null)
+ {
+ return e.getValue().getEncoded();
+ }
+ return null;
+ }
+
+ // GnuPKIExtension method.
+ // -------------------------------------------------------------------------
+
+ public Extension getExtension(OID oid)
+ {
+ return (Extension) extensions.get(oid);
+ }
+
+ public Collection getExtensions()
+ {
+ return extensions.values();
+ }
+
+ // Own methods.
+ // -------------------------------------------------------------------------
+
+ private void parse(int version, DERReader der) throws Exception
+ {
+ // RevokedCertificate ::= SEQUENCE {
+ DERValue entry = der.read();
+ debug("start CRL entry len == " + entry.getLength());
+ if (!entry.isConstructed())
+ throw new IOException("malformed revokedCertificate");
+ encoded = entry.getEncoded();
+ int len = 0;
+
+ debug("encoded entry:\n" + Util.hexDump(encoded, ">>>> "));
+
+ // userCertificate CertificateSerialNumber,
+ DERValue val = der.read();
+ serialNo = (BigInteger) val.getValue();
+ len += val.getEncodedLength();
+ debug("userCertificate == " + serialNo + " current count == " + len);
+
+ // revocationDate Time,
+ val = der.read();
+ revocationDate = (Date) val.getValue();
+ len += val.getEncodedLength();
+ debug("revocationDate == " + revocationDate + " current count == " + len);
+
+ // crlEntryExtensions Extensions OPTIONAL
+ // -- if present MUST be v2
+ if (len < entry.getLength())
+ {
+ if (version < 2)
+ throw new IOException("extra data in CRL entry");
+ DERValue exts = der.read();
+ if (!exts.isConstructed())
+ throw new IOException("malformed Extensions");
+ debug("start Extensions len == " + exts.getLength());
+ len = 0;
+ while (len < exts.getLength())
+ {
+ val = der.read();
+ if (!val.isConstructed())
+ throw new IOException("malformed Extension");
+ debug("start Extension len == " + val.getLength());
+ Extension e = new Extension(val.getEncoded());
+ extensions.put(e.getOid(), e);
+ der.skip(val.getLength());
+ len += val.getEncodedLength();
+ debug("current count == " + len);
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/x509/X509CRLSelectorImpl.java b/libjava/classpath/gnu/java/security/x509/X509CRLSelectorImpl.java
new file mode 100644
index 00000000000..0ada5501689
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/X509CRLSelectorImpl.java
@@ -0,0 +1,138 @@
+/* X509CRLSelectorImpl.java -- implementation of an X509CRLSelector.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.x509;
+
+import java.io.IOException;
+
+import java.security.Principal;
+import java.security.cert.CRL;
+import java.security.cert.CRLSelector;
+import java.security.cert.X509CRL;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.security.auth.x500.X500Principal;
+
+/**
+ * Sun's implementation of X509CRLSelector sucks. This one tries to work
+ * better.
+ */
+public class X509CRLSelectorImpl implements CRLSelector
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private Set issuerNames;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public X509CRLSelectorImpl()
+ {
+ issuerNames = new HashSet();
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public void addIssuerName(byte[] issuerName) throws IOException
+ {
+ issuerNames.add(new X500DistinguishedName(issuerName));
+ }
+
+ public void addIssuerName(String issuerName)
+ {
+ issuerNames.add(new X500DistinguishedName(issuerName));
+ }
+
+ public void addIssuerName(Principal issuerName) throws IOException
+ {
+ if (issuerName instanceof X500DistinguishedName)
+ issuerNames.add(issuerName);
+ else if (issuerName instanceof X500Principal)
+ issuerNames.add(new X500DistinguishedName(((X500Principal) issuerName).getEncoded()));
+ else
+ issuerNames.add(new X500DistinguishedName(issuerName.getName()));
+ }
+
+ public Collection getIssuerNames()
+ {
+ return Collections.unmodifiableSet(issuerNames);
+ }
+
+ public Object clone()
+ {
+ X509CRLSelectorImpl copy = new X509CRLSelectorImpl();
+ copy.issuerNames.addAll(issuerNames);
+ return copy;
+ }
+
+ public boolean match(CRL crl)
+ {
+ if (!(crl instanceof X509CRL))
+ return false;
+ try
+ {
+ Principal p = ((X509CRL) crl).getIssuerDN();
+ X500DistinguishedName thisName = null;
+ if (p instanceof X500DistinguishedName)
+ thisName = (X500DistinguishedName) p;
+ else if (p instanceof X500Principal)
+ thisName = new X500DistinguishedName(((X500Principal) p).getEncoded());
+ else
+ thisName = new X500DistinguishedName(p.getName());
+ for (Iterator it = issuerNames.iterator(); it.hasNext(); )
+ {
+ X500DistinguishedName name = (X500DistinguishedName) it.next();
+ if (thisName.equals(name))
+ return true;
+ }
+ }
+ catch (Exception x)
+ {
+ }
+ return false;
+ }
+}
+
diff --git a/libjava/classpath/gnu/java/security/x509/X509CertPath.java b/libjava/classpath/gnu/java/security/x509/X509CertPath.java
new file mode 100644
index 00000000000..e8ed6bf35d1
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/X509CertPath.java
@@ -0,0 +1,303 @@
+/* X509CertPath.java -- an X.509 certificate path.
+ Copyright (C) 2004 Free Software Fonudation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.x509;
+
+import gnu.java.security.OID;
+import gnu.java.security.der.DER;
+import gnu.java.security.der.DEREncodingException;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.security.cert.CertPath;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * A certificate path (or certificate chain) of X509Certificates.
+ *
+ * @author Casey Marshall (rsdio@metastatic.org)
+ */
+public class X509CertPath extends CertPath
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ public static final List ENCODINGS = Collections.unmodifiableList(
+ Arrays.asList(new String[] { "PkiPath", "PKCS7" }));
+
+ private static final OID PKCS7_SIGNED_DATA = new OID("1.2.840.113549.1.7.2");
+ private static final OID PKCS7_DATA = new OID("1.2.840.113549.1.7.1");
+
+ /** The certificate path. */
+ private List path;
+
+ /** The cached PKCS #7 encoded bytes. */
+ private byte[] pkcs_encoded;
+
+ /** The cached PkiPath encoded bytes. */
+ private byte[] pki_encoded;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public X509CertPath(List path)
+ {
+ super("X.509");
+ this.path = Collections.unmodifiableList(path);
+ }
+
+ public X509CertPath(InputStream in) throws CertificateEncodingException
+ {
+ this(in, (String) ENCODINGS.get(0));
+ }
+
+ public X509CertPath(InputStream in, String encoding)
+ throws CertificateEncodingException
+ {
+ super("X.509");
+ try
+ {
+ parse(in, encoding);
+ }
+ catch (IOException ioe)
+ {
+ throw new CertificateEncodingException();
+ }
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public List getCertificates()
+ {
+ return path; // already unmodifiable
+ }
+
+ public byte[] getEncoded() throws CertificateEncodingException
+ {
+ return getEncoded((String) ENCODINGS.get(0));
+ }
+
+ public byte[] getEncoded(String encoding) throws CertificateEncodingException
+ {
+ if (encoding.equalsIgnoreCase("PkiPath"))
+ {
+ if (pki_encoded == null)
+ {
+ try
+ {
+ pki_encoded = encodePki();
+ }
+ catch (IOException ioe)
+ {
+ throw new CertificateEncodingException();
+ }
+ }
+ return (byte[]) pki_encoded.clone();
+ }
+ else if (encoding.equalsIgnoreCase("PKCS7"))
+ {
+ if (pkcs_encoded == null)
+ {
+ try
+ {
+ pkcs_encoded = encodePKCS();
+ }
+ catch (IOException ioe)
+ {
+ throw new CertificateEncodingException();
+ }
+ }
+ return (byte[]) pkcs_encoded.clone();
+ }
+ else
+ throw new CertificateEncodingException("unknown encoding: " + encoding);
+ }
+
+ public Iterator getEncodings()
+ {
+ return ENCODINGS.iterator(); // already unmodifiable
+ }
+
+ // Own methods.
+ // -------------------------------------------------------------------------
+
+ private void parse(InputStream in, String encoding)
+ throws CertificateEncodingException, IOException
+ {
+ DERReader der = new DERReader(in);
+ DERValue path = null;
+ if (encoding.equalsIgnoreCase("PkiPath"))
+ {
+ // PKI encoding is just a SEQUENCE of X.509 certificates.
+ path = der.read();
+ if (!path.isConstructed())
+ throw new DEREncodingException("malformed PkiPath");
+ }
+ else if (encoding.equalsIgnoreCase("PKCS7"))
+ {
+ // PKCS #7 encoding means that the certificates are contained in a
+ // SignedData PKCS #7 type.
+ //
+ // ContentInfo ::= SEQUENCE {
+ // contentType ::= ContentType,
+ // content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+ //
+ // ContentType ::= OBJECT IDENTIFIER
+ //
+ // SignedData ::= SEQUENCE {
+ // version Version,
+ // digestAlgorithms DigestAlgorithmIdentifiers,
+ // contentInfo ContentInfo,
+ // certificates [0] IMPLICIT ExtendedCertificatesAndCertificates
+ // OPTIONAL,
+ // crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+ // signerInfos SignerInfos }
+ //
+ // Version ::= INTEGER
+ //
+ DERValue value = der.read();
+ if (!value.isConstructed())
+ throw new DEREncodingException("malformed ContentInfo");
+ value = der.read();
+ if (!(value.getValue() instanceof OID) ||
+ ((OID) value.getValue()).equals(PKCS7_SIGNED_DATA))
+ throw new DEREncodingException("not a SignedData");
+ value = der.read();
+ if (!value.isConstructed() || value.getTag() != 0)
+ throw new DEREncodingException("malformed content");
+ value = der.read();
+ if (value.getTag() != DER.INTEGER)
+ throw new DEREncodingException("malformed Version");
+ value = der.read();
+ if (!value.isConstructed() || value.getTag() != DER.SET)
+ throw new DEREncodingException("malformed DigestAlgorithmIdentifiers");
+ der.skip(value.getLength());
+ value = der.read();
+ if (!value.isConstructed())
+ throw new DEREncodingException("malformed ContentInfo");
+ der.skip(value.getLength());
+ path = der.read();
+ if (!path.isConstructed() || path.getTag() != 0)
+ throw new DEREncodingException("no certificates");
+ }
+ else
+ throw new CertificateEncodingException("unknown encoding: " + encoding);
+
+ LinkedList certs = new LinkedList();
+ int len = 0;
+ while (len < path.getLength())
+ {
+ DERValue cert = der.read();
+ try
+ {
+ certs.add(new X509Certificate(new ByteArrayInputStream(cert.getEncoded())));
+ }
+ catch (CertificateException ce)
+ {
+ throw new CertificateEncodingException(ce.getMessage());
+ }
+ len += cert.getEncodedLength();
+ der.skip(cert.getLength());
+ }
+
+ this.path = Collections.unmodifiableList(certs);
+ }
+
+ private byte[] encodePki()
+ throws CertificateEncodingException, IOException
+ {
+ synchronized (path)
+ {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ for (Iterator i = path.iterator(); i.hasNext(); )
+ {
+ out.write(((Certificate) i.next()).getEncoded());
+ }
+ byte[] b = out.toByteArray();
+ DERValue val = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
+ b.length, b, null);
+ return val.getEncoded();
+ }
+ }
+
+ private byte[] encodePKCS()
+ throws CertificateEncodingException, IOException
+ {
+ synchronized (path)
+ {
+ ArrayList signedData = new ArrayList(5);
+ signedData.add(new DERValue(DER.INTEGER, BigInteger.ONE));
+ signedData.add(new DERValue(DER.CONSTRUCTED | DER.SET,
+ Collections.EMPTY_SET));
+ signedData.add(new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
+ Collections.singletonList(
+ new DERValue(DER.OBJECT_IDENTIFIER, PKCS7_DATA))));
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ for (Iterator i = path.iterator(); i.hasNext(); )
+ {
+ out.write(((Certificate) i.next()).getEncoded());
+ }
+ byte[] b = out.toByteArray();
+ signedData.add(new DERValue(DER.CONSTRUCTED | DER.CONTEXT,
+ b.length, b, null));
+ DERValue sdValue = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
+ signedData);
+
+ ArrayList contentInfo = new ArrayList(2);
+ contentInfo.add(new DERValue(DER.OBJECT_IDENTIFIER, PKCS7_SIGNED_DATA));
+ contentInfo.add(new DERValue(DER.CONSTRUCTED | DER.CONTEXT, sdValue));
+ return new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
+ contentInfo).getEncoded();
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/x509/X509CertSelectorImpl.java b/libjava/classpath/gnu/java/security/x509/X509CertSelectorImpl.java
new file mode 100644
index 00000000000..36187ad8e64
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/X509CertSelectorImpl.java
@@ -0,0 +1,197 @@
+/* X509CertSelectorImpl.java -- implementation of an X509CertSelector.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.x509;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.security.cert.CertSelector;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.security.auth.x500.X500Principal;
+
+/**
+ * Sun's implementation of X509CertSelector sucks. This one tries to work
+ * better.
+ */
+public class X509CertSelectorImpl implements CertSelector
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private Set issuerNames;
+ private Set subjectNames;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public X509CertSelectorImpl()
+ {
+ issuerNames = new HashSet();
+ subjectNames = new HashSet();
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public void addIssuerName(byte[] issuerName) throws IOException
+ {
+ issuerNames.add(new X500DistinguishedName(issuerName));
+ }
+
+ public void addIssuerName(String issuerName)
+ {
+ issuerNames.add(new X500DistinguishedName(issuerName));
+ }
+
+ public void addIssuerName(Principal issuerName) throws IOException
+ {
+ if (issuerName instanceof X500DistinguishedName)
+ issuerNames.add(issuerName);
+ else if (issuerName instanceof X500Principal)
+ issuerNames.add(new X500DistinguishedName(((X500Principal) issuerName).getEncoded()));
+ else
+ issuerNames.add(new X500DistinguishedName(issuerName.getName()));
+ }
+
+ public Collection getIssuerNames()
+ {
+ return Collections.unmodifiableSet(issuerNames);
+ }
+
+ public void addSubjectName(byte[] subjectName) throws IOException
+ {
+ subjectNames.add(new X500DistinguishedName(subjectName));
+ }
+
+ public void addSubjectName(String subjectName) throws IOException
+ {
+ subjectNames.add(new X500DistinguishedName(subjectName));
+ }
+
+ public void addSubjectName(Principal subjectName) throws IOException
+ {
+ if (subjectName instanceof X500DistinguishedName)
+ subjectNames.add(subjectName);
+ else if (subjectName instanceof X500Principal)
+ subjectNames.add(new X500DistinguishedName(((X500Principal) subjectName).getEncoded()));
+ else
+ subjectNames.add(new X500DistinguishedName(subjectName.getName()));
+ }
+
+ public Collection getSubjectNames()
+ {
+ return Collections.unmodifiableSet(subjectNames);
+ }
+
+ public Object clone()
+ {
+ X509CertSelectorImpl copy = new X509CertSelectorImpl();
+ copy.issuerNames.addAll(issuerNames);
+ copy.subjectNames.addAll(subjectNames);
+ return copy;
+ }
+
+ public boolean match(Certificate cert)
+ {
+ if (!(cert instanceof X509Certificate))
+ return false;
+ boolean matchIssuer = false;
+ boolean matchSubject = false;
+ try
+ {
+ Principal p = ((X509Certificate) cert).getIssuerDN();
+ X500DistinguishedName thisName = null;
+ if (p instanceof X500DistinguishedName)
+ thisName = (X500DistinguishedName) p;
+ else if (p instanceof X500Principal)
+ thisName = new X500DistinguishedName(((X500Principal) p).getEncoded());
+ else
+ thisName = new X500DistinguishedName(p.getName());
+ if (issuerNames.isEmpty())
+ matchIssuer = true;
+ else
+ {
+ for (Iterator it = issuerNames.iterator(); it.hasNext(); )
+ {
+ X500DistinguishedName name = (X500DistinguishedName) it.next();
+ if (thisName.equals(name))
+ {
+ matchIssuer = true;
+ break;
+ }
+ }
+ }
+
+ p = ((X509Certificate) cert).getSubjectDN();
+ thisName = null;
+ if (p instanceof X500DistinguishedName)
+ thisName = (X500DistinguishedName) p;
+ else if (p instanceof X500Principal)
+ thisName = new X500DistinguishedName(((X500Principal) p).getEncoded());
+ else
+ thisName = new X500DistinguishedName(p.getName());
+ if (subjectNames.isEmpty())
+ matchSubject = true;
+ else
+ {
+ for (Iterator it = subjectNames.iterator(); it.hasNext(); )
+ {
+ X500DistinguishedName name = (X500DistinguishedName) it.next();
+ if (thisName.equals(name))
+ {
+ matchSubject = true;
+ break;
+ }
+ }
+ }
+ }
+ catch (Exception x)
+ {
+ }
+ return matchIssuer && matchSubject;
+ }
+}
+
diff --git a/libjava/classpath/gnu/java/security/x509/X509Certificate.java b/libjava/classpath/gnu/java/security/x509/X509Certificate.java
new file mode 100644
index 00000000000..14ac43a25e6
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/X509Certificate.java
@@ -0,0 +1,745 @@
+/* X509Certificate.java -- X.509 certificate.
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.x509;
+
+import gnu.classpath.debug.Component;
+import gnu.classpath.debug.SystemLogger;
+
+import gnu.java.security.OID;
+import gnu.java.security.der.BitString;
+import gnu.java.security.der.DER;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+import gnu.java.security.x509.ext.BasicConstraints;
+import gnu.java.security.x509.ext.ExtendedKeyUsage;
+import gnu.java.security.x509.ext.Extension;
+import gnu.java.security.x509.ext.IssuerAlternativeNames;
+import gnu.java.security.x509.ext.KeyUsage;
+import gnu.java.security.x509.ext.SubjectAlternativeNames;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.io.StringWriter;
+import java.math.BigInteger;
+import java.security.AlgorithmParameters;
+import java.security.InvalidKeyException;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Principal;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.CertificateParsingException;
+import java.security.interfaces.DSAParams;
+import java.security.interfaces.DSAPublicKey;
+import java.security.spec.DSAParameterSpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.security.auth.x500.X500Principal;
+
+/**
+ * An implementation of X.509 certificates.
+ *
+ * @author Casey Marshall (rsdio@metastatic.org)
+ */
+public class X509Certificate extends java.security.cert.X509Certificate
+ implements Serializable, GnuPKIExtension
+{
+
+ // Constants and fields.
+ // ------------------------------------------------------------------------
+
+ private static final Logger logger = SystemLogger.SYSTEM;
+
+ protected static final OID ID_DSA = new OID ("1.2.840.10040.4.1");
+ protected static final OID ID_DSA_WITH_SHA1 = new OID ("1.2.840.10040.4.3");
+ protected static final OID ID_RSA = new OID ("1.2.840.113549.1.1.1");
+ protected static final OID ID_RSA_WITH_MD2 = new OID ("1.2.840.113549.1.1.2");
+ protected static final OID ID_RSA_WITH_MD5 = new OID ("1.2.840.113549.1.1.4");
+ protected static final OID ID_RSA_WITH_SHA1 = new OID ("1.2.840.113549.1.1.5");
+ protected static final OID ID_ECDSA_WITH_SHA1 = new OID ("1.2.840.10045.4.1");
+
+ // This object SHOULD be serialized with an instance of
+ // java.security.cert.Certificate.CertificateRep, thus all fields are
+ // transient.
+
+ // The encoded certificate.
+ protected transient byte[] encoded;
+
+ // TBSCertificate part.
+ protected transient byte[] tbsCertBytes;
+ protected transient int version;
+ protected transient BigInteger serialNo;
+ protected transient OID algId;
+ protected transient byte[] algVal;
+ protected transient X500DistinguishedName issuer;
+ protected transient Date notBefore;
+ protected transient Date notAfter;
+ protected transient X500DistinguishedName subject;
+ protected transient PublicKey subjectKey;
+ protected transient BitString issuerUniqueId;
+ protected transient BitString subjectUniqueId;
+ protected transient Map extensions;
+
+ // Signature.
+ protected transient OID sigAlgId;
+ protected transient byte[] sigAlgVal;
+ protected transient byte[] signature;
+
+ // Constructors.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Create a new X.509 certificate from the encoded data. The input
+ * data are expected to be the ASN.1 DER encoding of the certificate.
+ *
+ * @param encoded The encoded certificate data.
+ * @throws IOException If the certificate cannot be read, possibly
+ * from a formatting error.
+ * @throws CertificateException If the data read is not an X.509
+ * certificate.
+ */
+ public X509Certificate(InputStream encoded)
+ throws CertificateException, IOException
+ {
+ super();
+ extensions = new HashMap();
+ try
+ {
+ parse(encoded);
+ }
+ catch (IOException ioe)
+ {
+ logger.log (Component.X509, "", ioe);
+ throw ioe;
+ }
+ catch (Exception e)
+ {
+ logger.log (Component.X509, "", e);
+ CertificateException ce = new CertificateException(e.getMessage());
+ ce.initCause (e);
+ throw ce;
+ }
+ }
+
+ protected X509Certificate()
+ {
+ extensions = new HashMap();
+ }
+
+ // X509Certificate methods.
+ // ------------------------------------------------------------------------
+
+ public void checkValidity()
+ throws CertificateExpiredException, CertificateNotYetValidException
+ {
+ checkValidity(new Date());
+ }
+
+ public void checkValidity(Date date)
+ throws CertificateExpiredException, CertificateNotYetValidException
+ {
+ if (date.compareTo(notBefore) < 0)
+ {
+ throw new CertificateNotYetValidException();
+ }
+ if (date.compareTo(notAfter) > 0)
+ {
+ throw new CertificateExpiredException();
+ }
+ }
+
+ public int getVersion()
+ {
+ return version;
+ }
+
+ public BigInteger getSerialNumber()
+ {
+ return serialNo;
+ }
+
+ public Principal getIssuerDN()
+ {
+ return issuer;
+ }
+
+ public X500Principal getIssuerX500Principal()
+ {
+ return new X500Principal(issuer.getDer());
+ }
+
+ public Principal getSubjectDN()
+ {
+ return subject;
+ }
+
+ public X500Principal getSubjectX500Principal()
+ {
+ return new X500Principal(subject.getDer());
+ }
+
+ public Date getNotBefore()
+ {
+ return (Date) notBefore.clone();
+ }
+
+ public Date getNotAfter()
+ {
+ return (Date) notAfter.clone();
+ }
+
+ public byte[] getTBSCertificate() throws CertificateEncodingException
+ {
+ return (byte[]) tbsCertBytes.clone();
+ }
+
+ public byte[] getSignature()
+ {
+ return (byte[]) signature.clone();
+ }
+
+ public String getSigAlgName()
+ {
+ if (sigAlgId.equals(ID_DSA_WITH_SHA1))
+ {
+ return "SHA1withDSA";
+ }
+ if (sigAlgId.equals(ID_RSA_WITH_MD2))
+ {
+ return "MD2withRSA";
+ }
+ if (sigAlgId.equals(ID_RSA_WITH_MD5))
+ {
+ return "MD5withRSA";
+ }
+ if (sigAlgId.equals(ID_RSA_WITH_SHA1))
+ {
+ return "SHA1withRSA";
+ }
+ return "unknown";
+ }
+
+ public String getSigAlgOID()
+ {
+ return sigAlgId.toString();
+ }
+
+ public byte[] getSigAlgParams()
+ {
+ return (byte[]) sigAlgVal.clone();
+ }
+
+ public boolean[] getIssuerUniqueID()
+ {
+ if (issuerUniqueId != null)
+ {
+ return issuerUniqueId.toBooleanArray();
+ }
+ return null;
+ }
+
+ public boolean[] getSubjectUniqueID()
+ {
+ if (subjectUniqueId != null)
+ {
+ return subjectUniqueId.toBooleanArray();
+ }
+ return null;
+ }
+
+ public boolean[] getKeyUsage()
+ {
+ Extension e = getExtension(KeyUsage.ID);
+ if (e != null)
+ {
+ KeyUsage ku = (KeyUsage) e.getValue();
+ boolean[] result = new boolean[9];
+ boolean[] b = ku.getKeyUsage().toBooleanArray();
+ System.arraycopy(b, 0, result, 0, b.length);
+ return result;
+ }
+ return null;
+ }
+
+ public List getExtendedKeyUsage() throws CertificateParsingException
+ {
+ Extension e = getExtension(ExtendedKeyUsage.ID);
+ if (e != null)
+ {
+ List a = ((ExtendedKeyUsage) e.getValue()).getPurposeIds();
+ List b = new ArrayList(a.size());
+ for (Iterator it = a.iterator(); it.hasNext(); )
+ {
+ b.add(it.next().toString());
+ }
+ return Collections.unmodifiableList(b);
+ }
+ return null;
+ }
+
+ public int getBasicConstraints()
+ {
+ Extension e = getExtension(BasicConstraints.ID);
+ if (e != null)
+ {
+ return ((BasicConstraints) e.getValue()).getPathLengthConstraint();
+ }
+ return -1;
+ }
+
+ public Collection getSubjectAlternativeNames()
+ throws CertificateParsingException
+ {
+ Extension e = getExtension(SubjectAlternativeNames.ID);
+ if (e != null)
+ {
+ return ((SubjectAlternativeNames) e.getValue()).getNames();
+ }
+ return null;
+ }
+
+ public Collection getIssuerAlternativeNames()
+ throws CertificateParsingException
+ {
+ Extension e = getExtension(IssuerAlternativeNames.ID);
+ if (e != null)
+ {
+ return ((IssuerAlternativeNames) e.getValue()).getNames();
+ }
+ return null;
+ }
+
+ // X509Extension methods.
+ // ------------------------------------------------------------------------
+
+ public boolean hasUnsupportedCriticalExtension()
+ {
+ for (Iterator it = extensions.values().iterator(); it.hasNext(); )
+ {
+ Extension e = (Extension) it.next();
+ if (e.isCritical() && !e.isSupported())
+ return true;
+ }
+ return false;
+ }
+
+ public Set getCriticalExtensionOIDs()
+ {
+ HashSet s = new HashSet();
+ for (Iterator it = extensions.values().iterator(); it.hasNext(); )
+ {
+ Extension e = (Extension) it.next();
+ if (e.isCritical())
+ s.add(e.getOid().toString());
+ }
+ return Collections.unmodifiableSet(s);
+ }
+
+ public Set getNonCriticalExtensionOIDs()
+ {
+ HashSet s = new HashSet();
+ for (Iterator it = extensions.values().iterator(); it.hasNext(); )
+ {
+ Extension e = (Extension) it.next();
+ if (!e.isCritical())
+ s.add(e.getOid().toString());
+ }
+ return Collections.unmodifiableSet(s);
+ }
+
+ public byte[] getExtensionValue(String oid)
+ {
+ Extension e = getExtension(new OID(oid));
+ if (e != null)
+ {
+ return e.getValue().getEncoded();
+ }
+ return null;
+ }
+
+ // GnuPKIExtension method.
+ // -------------------------------------------------------------------------
+
+ public Extension getExtension(OID oid)
+ {
+ return (Extension) extensions.get(oid);
+ }
+
+ public Collection getExtensions()
+ {
+ return extensions.values();
+ }
+
+ // Certificate methods.
+ // -------------------------------------------------------------------------
+
+ public byte[] getEncoded() throws CertificateEncodingException
+ {
+ return (byte[]) encoded.clone();
+ }
+
+ public void verify(PublicKey key)
+ throws CertificateException, NoSuchAlgorithmException,
+ InvalidKeyException, NoSuchProviderException, SignatureException
+ {
+ Signature sig = Signature.getInstance(sigAlgId.toString());
+ doVerify(sig, key);
+ }
+
+ public void verify(PublicKey key, String provider)
+ throws CertificateException, NoSuchAlgorithmException,
+ InvalidKeyException, NoSuchProviderException, SignatureException
+ {
+ Signature sig = Signature.getInstance(sigAlgId.toString(), provider);
+ doVerify(sig, key);
+ }
+
+ public String toString()
+ {
+ StringWriter str = new StringWriter();
+ PrintWriter out = new PrintWriter(str);
+ out.println(X509Certificate.class.getName() + " {");
+ out.println(" TBSCertificate {");
+ out.println(" version = " + version + ";");
+ out.println(" serialNo = " + serialNo + ";");
+ out.println(" signature = {");
+ out.println(" algorithm = " + getSigAlgName() + ";");
+ out.print(" parameters =");
+ if (sigAlgVal != null)
+ {
+ out.println();
+ out.print(Util.hexDump(sigAlgVal, " "));
+ }
+ else
+ {
+ out.println(" null;");
+ }
+ out.println(" }");
+ out.println(" issuer = " + issuer.getName() + ";");
+ out.println(" validity = {");
+ out.println(" notBefore = " + notBefore + ";");
+ out.println(" notAfter = " + notAfter + ";");
+ out.println(" }");
+ out.println(" subject = " + subject.getName() + ";");
+ out.println(" subjectPublicKeyInfo = {");
+ out.println(" algorithm = " + subjectKey.getAlgorithm());
+ out.println(" key =");
+ out.print(Util.hexDump(subjectKey.getEncoded(), " "));
+ out.println(" };");
+ out.println(" issuerUniqueId = " + issuerUniqueId + ";");
+ out.println(" subjectUniqueId = " + subjectUniqueId + ";");
+ out.println(" extensions = {");
+ for (Iterator it = extensions.values().iterator(); it.hasNext(); )
+ {
+ out.println(" " + it.next());
+ }
+ out.println(" }");
+ out.println(" }");
+ out.println(" signatureAlgorithm = " + getSigAlgName() + ";");
+ out.println(" signatureValue =");
+ out.print(Util.hexDump(signature, " "));
+ out.println("}");
+ return str.toString();
+ }
+
+ public PublicKey getPublicKey()
+ {
+ return subjectKey;
+ }
+
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof X509Certificate))
+ return false;
+ try
+ {
+ if (other instanceof X509Certificate)
+ return Arrays.equals(encoded, ((X509Certificate) other).encoded);
+ byte[] enc = ((X509Certificate) other).getEncoded();
+ if (enc == null)
+ return false;
+ return Arrays.equals(encoded, enc);
+ }
+ catch (CertificateEncodingException cee)
+ {
+ return false;
+ }
+ }
+
+ // Own methods.
+ // ------------------------------------------------------------------------
+
+ /**
+ * Verify this certificate's signature.
+ */
+ private void doVerify(Signature sig, PublicKey key)
+ throws CertificateException, InvalidKeyException, SignatureException
+ {
+ logger.log (Component.X509, "verifying sig={0} key={1}",
+ new Object[] { sig, key });
+ sig.initVerify(key);
+ sig.update(tbsCertBytes);
+ if (!sig.verify(signature))
+ {
+ throw new CertificateException("signature not validated");
+ }
+ }
+
+ /**
+ * Parse a DER stream into an X.509 certificate.
+ *
+ * @param encoded The encoded bytes.
+ */
+ private void parse(InputStream encoded) throws Exception
+ {
+ DERReader der = new DERReader(encoded);
+
+ // Certificate ::= SEQUENCE {
+ DERValue cert = der.read();
+ logger.log (Component.X509, "start Certificate len == {0}",
+ new Integer (cert.getLength()));
+
+ this.encoded = cert.getEncoded();
+ if (!cert.isConstructed())
+ {
+ throw new IOException("malformed Certificate");
+ }
+
+ // TBSCertificate ::= SEQUENCE {
+ DERValue tbsCert = der.read();
+ if (tbsCert.getValue() != DER.CONSTRUCTED_VALUE)
+ {
+ throw new IOException("malformed TBSCertificate");
+ }
+ tbsCertBytes = tbsCert.getEncoded();
+ logger.log (Component.X509, "start TBSCertificate len == {0}",
+ new Integer (tbsCert.getLength()));
+
+ // Version ::= INTEGER [0] { v1(0), v2(1), v3(2) }
+ DERValue val = der.read();
+ if (val.getTagClass() == DER.CONTEXT && val.getTag() == 0)
+ {
+ version = ((BigInteger) der.read().getValue()).intValue() + 1;
+ val = der.read();
+ }
+ else
+ {
+ version = 1;
+ }
+ logger.log (Component.X509, "read version == {0}",
+ new Integer (version));
+
+ // SerialNumber ::= INTEGER
+ serialNo = (BigInteger) val.getValue();
+ logger.log (Component.X509, "read serial number == {0}", serialNo);
+
+ // AlgorithmIdentifier ::= SEQUENCE {
+ val = der.read();
+ if (!val.isConstructed())
+ {
+ throw new IOException("malformed AlgorithmIdentifier");
+ }
+ int certAlgLen = val.getLength();
+ logger.log (Component.X509, "start AlgorithmIdentifier len == {0}",
+ new Integer (certAlgLen));
+ val = der.read();
+
+ // algorithm OBJECT IDENTIFIER,
+ algId = (OID) val.getValue();
+ logger.log (Component.X509, "read algorithm ID == {0}", algId);
+
+ // parameters ANY DEFINED BY algorithm OPTIONAL }
+ if (certAlgLen > val.getEncodedLength())
+ {
+ val = der.read();
+ if (val == null)
+ {
+ algVal = null;
+ }
+ else
+ {
+ algVal = val.getEncoded();
+
+ if (val.isConstructed())
+ encoded.skip(val.getLength());
+ }
+ logger.log (Component.X509, "read algorithm parameters == {0}", algVal);
+ }
+
+ // issuer Name,
+ val = der.read();
+ issuer = new X500DistinguishedName(val.getEncoded());
+ der.skip(val.getLength());
+ logger.log (Component.X509, "read issuer == {0}", issuer);
+
+ // Validity ::= SEQUENCE {
+ // notBefore Time,
+ // notAfter Time }
+ if (!der.read().isConstructed())
+ {
+ throw new IOException("malformed Validity");
+ }
+ notBefore = (Date) der.read().getValue();
+ logger.log (Component.X509, "read notBefore == {0}", notBefore);
+ notAfter = (Date) der.read().getValue();
+ logger.log (Component.X509, "read notAfter == {0}", notAfter);
+
+ // subject Name,
+ val = der.read();
+ subject = new X500DistinguishedName(val.getEncoded());
+ der.skip(val.getLength());
+ logger.log (Component.X509, "read subject == {0}", subject);
+
+ // SubjectPublicKeyInfo ::= SEQUENCE {
+ // algorithm AlgorithmIdentifier,
+ // subjectPublicKey BIT STRING }
+ DERValue spki = der.read();
+ if (!spki.isConstructed())
+ {
+ throw new IOException("malformed SubjectPublicKeyInfo");
+ }
+ KeyFactory spkFac = KeyFactory.getInstance("X.509");
+ subjectKey = spkFac.generatePublic(new X509EncodedKeySpec(spki.getEncoded()));
+ der.skip(spki.getLength());
+ logger.log (Component.X509, "read subjectPublicKey == {0}", subjectKey);
+
+ if (version > 1)
+ {
+ val = der.read();
+ }
+ if (version >= 2 && val.getTagClass() != DER.UNIVERSAL && val.getTag() == 1)
+ {
+ byte[] b = (byte[]) val.getValue();
+ issuerUniqueId = new BitString(b, 1, b.length-1, b[0] & 0xFF);
+ logger.log (Component.X509, "read issuerUniqueId == {0}", issuerUniqueId);
+ val = der.read();
+ }
+ if (version >= 2 && val.getTagClass() != DER.UNIVERSAL && val.getTag() == 2)
+ {
+ byte[] b = (byte[]) val.getValue();
+ subjectUniqueId = new BitString(b, 1, b.length-1, b[0] & 0xFF);
+ logger.log (Component.X509, "read subjectUniqueId == {0}", subjectUniqueId);
+ val = der.read();
+ }
+ if (version >= 3 && val.getTagClass() != DER.UNIVERSAL && val.getTag() == 3)
+ {
+ val = der.read();
+ logger.log (Component.X509, "start Extensions len == {0}",
+ new Integer (val.getLength()));
+ int len = 0;
+ while (len < val.getLength())
+ {
+ DERValue ext = der.read();
+ logger.log (Component.X509, "start extension len == {0}",
+ new Integer (ext.getLength()));
+ Extension e = new Extension(ext.getEncoded());
+ extensions.put(e.getOid(), e);
+ der.skip(ext.getLength());
+ len += ext.getEncodedLength();
+ logger.log (Component.X509, "read extension {0} == {1}",
+ new Object[] { e.getOid (), e });
+ logger.log (Component.X509, "count == {0}", new Integer (len));
+ }
+
+ val = der.read ();
+ }
+
+ logger.log (Component.X509, "read value {0}", val);
+ if (!val.isConstructed())
+ {
+ throw new CertificateException ("malformed AlgorithmIdentifier");
+ }
+ int sigAlgLen = val.getLength();
+ logger.log (Component.X509, "start AlgorithmIdentifier len == {0}",
+ new Integer (sigAlgLen));
+ val = der.read();
+ sigAlgId = (OID) val.getValue();
+ logger.log (Component.X509, "read algorithm id == {0}", sigAlgId);
+ if (sigAlgLen > val.getEncodedLength())
+ {
+ val = der.read();
+ if (val.getValue() == null)
+ {
+ if (subjectKey instanceof DSAPublicKey)
+ {
+ AlgorithmParameters params =
+ AlgorithmParameters.getInstance("DSA");
+ DSAParams dsap = ((DSAPublicKey) subjectKey).getParams();
+ DSAParameterSpec spec =
+ new DSAParameterSpec(dsap.getP(), dsap.getQ(), dsap.getG());
+ params.init(spec);
+ sigAlgVal = params.getEncoded();
+ }
+ }
+ else
+ {
+ sigAlgVal = (byte[]) val.getEncoded();
+ }
+ if (val.isConstructed())
+ {
+ encoded.skip(val.getLength());
+ }
+ logger.log (Component.X509, "read parameters == {0}", sigAlgVal);
+ }
+ signature = ((BitString) der.read().getValue()).toByteArray();
+ logger.log (Component.X509, "read signature ==\n{0}", Util.hexDump(signature, ">>>> "));
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/x509/ext/AuthorityKeyIdentifier.java b/libjava/classpath/gnu/java/security/x509/ext/AuthorityKeyIdentifier.java
new file mode 100644
index 00000000000..a94b76f093e
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/ext/AuthorityKeyIdentifier.java
@@ -0,0 +1,133 @@
+/* AuthorityKeyIdentifier.java -- Authority key identifier extension.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.x509.ext;
+
+import gnu.java.security.OID;
+import gnu.java.security.der.DER;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+import gnu.java.security.x509.Util;
+
+import java.io.IOException;
+import java.math.BigInteger;
+
+public class AuthorityKeyIdentifier extends Extension.Value
+{
+
+ // Constants and fields.
+ // -------------------------------------------------------------------------
+
+ public static final OID ID = new OID("2.5.29.35");
+
+ private final byte[] keyIdentifier;
+ private final GeneralNames authorityCertIssuer;
+ private final BigInteger authorityCertSerialNumber;
+
+ // Contstructor.
+ // -------------------------------------------------------------------------
+
+ public AuthorityKeyIdentifier(final byte[] encoded) throws IOException
+ {
+ super(encoded);
+ DERReader der = new DERReader(encoded);
+
+ // AuthorityKeyIdentifier ::= SEQUENCE {
+ DERValue val = der.read();
+ if (!val.isConstructed())
+ throw new IOException("malformed AuthorityKeyIdentifier");
+ if (val.getLength() > 0)
+ val = der.read();
+
+ // keyIdentifier [0] KeyIdentifier OPTIONAL,
+ // KeyIdentifier ::= OCTET STRING
+ if (val.getTagClass() == DER.APPLICATION && val.getTag() == 0)
+ {
+ keyIdentifier = (byte[]) val.getValue();
+ val = der.read();
+ }
+ else
+ keyIdentifier = null;
+
+ // authorityCertIssuer [1] GeneralNames OPTIONAL,
+ if (val.getTagClass() == DER.APPLICATION && val.getTag() == 1)
+ {
+ byte[] b = val.getEncoded();
+ b[0] = (byte) (DER.CONSTRUCTED|DER.SEQUENCE);
+ authorityCertIssuer = new GeneralNames(b);
+ der.skip(val.getLength());
+ val = der.read();
+ }
+ else
+ authorityCertIssuer = null;
+
+ // authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
+ if (val.getTagClass() == DER.APPLICATION && val.getTag() == 2)
+ {
+ authorityCertSerialNumber = new BigInteger((byte[]) val.getValue());
+ }
+ else
+ authorityCertSerialNumber = null;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public byte[] getKeyIdentifier()
+ {
+ return keyIdentifier != null ? (byte[]) keyIdentifier.clone() : null;
+ }
+
+ public GeneralNames getAuthorityCertIssuer()
+ {
+ return authorityCertIssuer;
+ }
+
+ public BigInteger getAuthorityCertSerialNumber()
+ {
+ return authorityCertSerialNumber;
+ }
+
+ public String toString()
+ {
+ return AuthorityKeyIdentifier.class.getName() + " [ keyId=" +
+ (keyIdentifier != null ? Util.toHexString (keyIdentifier, ':') : "nil") +
+ " authorityCertIssuer=" + authorityCertIssuer +
+ " authorityCertSerialNumbe=" + authorityCertSerialNumber + " ]";
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/x509/ext/BasicConstraints.java b/libjava/classpath/gnu/java/security/x509/ext/BasicConstraints.java
new file mode 100644
index 00000000000..00f7a6ed220
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/ext/BasicConstraints.java
@@ -0,0 +1,129 @@
+/* BasicConstraints.java -- the basic constraints extension.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.x509.ext;
+
+import gnu.java.security.OID;
+import gnu.java.security.der.DER;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+public class BasicConstraints extends Extension.Value
+{
+
+ // Constants and fields.
+ // -------------------------------------------------------------------------
+
+ public static final OID ID = new OID("2.5.29.19");
+
+ private final boolean ca;
+ private final int pathLenConstraint;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public BasicConstraints(final byte[] encoded) throws IOException
+ {
+ super(encoded);
+ DERReader der = new DERReader(encoded);
+ DERValue bc = der.read();
+ if (!bc.isConstructed())
+ throw new IOException("malformed BasicConstraints");
+ DERValue val = bc;
+ if (bc.getLength() > 0)
+ val = der.read();
+ if (val.getTag() == DER.BOOLEAN)
+ {
+ ca = ((Boolean) val.getValue()).booleanValue();
+ if (val.getEncodedLength() < bc.getLength())
+ val = der.read();
+ }
+ else
+ ca = false;
+ if (val.getTag() == DER.INTEGER)
+ {
+ pathLenConstraint = ((BigInteger) val.getValue()).intValue();
+ }
+ else
+ pathLenConstraint = -1;
+ }
+
+ public BasicConstraints (final boolean ca, final int pathLenConstraint)
+ {
+ this.ca = ca;
+ this.pathLenConstraint = pathLenConstraint;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public boolean isCA()
+ {
+ return ca;
+ }
+
+ public int getPathLengthConstraint()
+ {
+ return pathLenConstraint;
+ }
+
+ public byte[] getEncoded()
+ {
+ if (encoded == null)
+ {
+ List bc = new ArrayList (2);
+ bc.add (new DERValue (DER.BOOLEAN, new Boolean (ca)));
+ if (pathLenConstraint >= 0)
+ bc.add (new DERValue (DER.INTEGER,
+ BigInteger.valueOf ((long) pathLenConstraint)));
+ encoded = new DERValue (DER.CONSTRUCTED|DER.SEQUENCE, bc).getEncoded();
+ }
+ return (byte[]) encoded.clone();
+ }
+
+ public String toString()
+ {
+ return BasicConstraints.class.getName() + " [ isCA=" + ca +
+ " pathLen=" + pathLenConstraint + " ]";
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/x509/ext/CRLNumber.java b/libjava/classpath/gnu/java/security/x509/ext/CRLNumber.java
new file mode 100644
index 00000000000..36b1c7b5f1d
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/ext/CRLNumber.java
@@ -0,0 +1,97 @@
+/* CRLNumber.java -- CRL number extension.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.x509.ext;
+
+import gnu.java.security.OID;
+import gnu.java.security.der.DER;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+
+import java.io.IOException;
+import java.math.BigInteger;
+
+public class CRLNumber extends Extension.Value
+{
+
+ // Constants and fields.
+ // -------------------------------------------------------------------------
+
+ public static final OID ID = new OID("2.5.29.20");
+
+ private final BigInteger number;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public CRLNumber(final byte[] encoded) throws IOException
+ {
+ super(encoded);
+ DERValue val = DERReader.read(encoded);
+ if (val.getTag() != DER.INTEGER)
+ throw new IOException("malformed CRLNumber");
+ number = (BigInteger) val.getValue();
+ }
+
+ public CRLNumber (final BigInteger number)
+ {
+ this.number = number;
+ }
+
+ // Instance method.
+ // -------------------------------------------------------------------------
+
+ public BigInteger getNumber()
+ {
+ return number;
+ }
+
+ public byte[] getEncoded()
+ {
+ if (encoded == null)
+ {
+ encoded = new DERValue (DER.INTEGER, number).getEncoded();
+ }
+ return (byte[]) encoded.clone();
+ }
+
+ public String toString()
+ {
+ return CRLNumber.class.getName() + " [ " + number + " ]";
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/x509/ext/CertificatePolicies.java b/libjava/classpath/gnu/java/security/x509/ext/CertificatePolicies.java
new file mode 100644
index 00000000000..50bc6d367d7
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/ext/CertificatePolicies.java
@@ -0,0 +1,189 @@
+/* CertificatePolicies.java -- certificate policy extension.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.x509.ext;
+
+import gnu.java.security.OID;
+import gnu.java.security.der.DER;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+
+import java.io.IOException;
+import java.security.cert.PolicyQualifierInfo;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+public class CertificatePolicies extends Extension.Value
+{
+
+ // Constants and fields.
+ // -------------------------------------------------------------------------
+
+ public static final OID ID = new OID("2.5.29.32");
+
+ private final List policies;
+ private final Map policyQualifierInfos;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public CertificatePolicies(final byte[] encoded) throws IOException
+ {
+ super(encoded);
+ DERReader der = new DERReader(encoded);
+ DERValue pol = der.read();
+ if (!pol.isConstructed())
+ throw new IOException("malformed CertificatePolicies");
+
+ int len = 0;
+ LinkedList policyList = new LinkedList();
+ HashMap qualifierMap = new HashMap();
+ while (len < pol.getLength())
+ {
+ DERValue policyInfo = der.read();
+ if (!policyInfo.isConstructed())
+ throw new IOException("malformed PolicyInformation");
+ DERValue val = der.read();
+ if (val.getTag() != DER.OBJECT_IDENTIFIER)
+ throw new IOException("malformed CertPolicyId");
+ OID policyId = (OID) val.getValue();
+ policyList.add(policyId);
+ if (val.getEncodedLength() < policyInfo.getLength())
+ {
+ DERValue qual = der.read();
+ int len2 = 0;
+ LinkedList quals = new LinkedList();
+ while (len2 < qual.getLength())
+ {
+ val = der.read();
+ quals.add(new PolicyQualifierInfo(val.getEncoded()));
+ der.skip(val.getLength());
+ len2 += val.getEncodedLength();
+ }
+ qualifierMap.put(policyId, quals);
+ }
+ len += policyInfo.getEncodedLength();
+ }
+
+ policies = Collections.unmodifiableList(policyList);
+ policyQualifierInfos = Collections.unmodifiableMap(qualifierMap);
+ }
+
+ public CertificatePolicies (final List policies,
+ final Map policyQualifierInfos)
+ {
+ for (Iterator it = policies.iterator(); it.hasNext(); )
+ if (!(it.next() instanceof OID))
+ throw new IllegalArgumentException ("policies must be OIDs");
+ for (Iterator it = policyQualifierInfos.entrySet().iterator(); it.hasNext();)
+ {
+ Map.Entry e = (Map.Entry) it.next();
+ if (!(e.getKey() instanceof OID) || !policies.contains (e.getKey()))
+ throw new IllegalArgumentException
+ ("policyQualifierInfos keys must be OIDs");
+ if (!(e.getValue() instanceof List))
+ throw new IllegalArgumentException
+ ("policyQualifierInfos values must be Lists of PolicyQualifierInfos");
+ for (Iterator it2 = ((List) e.getValue()).iterator(); it.hasNext(); )
+ if (!(it2.next() instanceof PolicyQualifierInfo))
+ throw new IllegalArgumentException
+ ("policyQualifierInfos values must be Lists of PolicyQualifierInfos");
+ }
+ this.policies = Collections.unmodifiableList (new ArrayList (policies));
+ this.policyQualifierInfos = Collections.unmodifiableMap
+ (new HashMap (policyQualifierInfos));
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public List getPolicies()
+ {
+ return policies;
+ }
+
+ public List getPolicyQualifierInfos(OID oid)
+ {
+ return (List) policyQualifierInfos.get(oid);
+ }
+
+ public byte[] getEncoded()
+ {
+ if (encoded == null)
+ {
+ List pol = new ArrayList (policies.size());
+ for (Iterator it = policies.iterator(); it.hasNext(); )
+ {
+ OID policy = (OID) it.next();
+ List qualifiers = getPolicyQualifierInfos (policy);
+ List l = new ArrayList (qualifiers == null ? 1 : 2);
+ l.add (new DERValue (DER.OBJECT_IDENTIFIER, policy));
+ if (qualifiers != null)
+ {
+ List ll = new ArrayList (qualifiers.size());
+ for (Iterator it2 = qualifiers.iterator(); it.hasNext(); )
+ {
+ PolicyQualifierInfo info = (PolicyQualifierInfo) it2.next();
+ try
+ {
+ ll.add (DERReader.read (info.getEncoded()));
+ }
+ catch (IOException ioe)
+ {
+ }
+ }
+ l.add (new DERValue (DER.CONSTRUCTED|DER.SEQUENCE, ll));
+ }
+ pol.add (new DERValue (DER.CONSTRUCTED|DER.SEQUENCE, l));
+ }
+ encoded = new DERValue (DER.CONSTRUCTED|DER.SEQUENCE, pol).getEncoded();
+ }
+ return (byte[]) encoded.clone();
+ }
+
+ public String toString()
+ {
+ return CertificatePolicies.class.getName() + " [ policies=" + policies +
+ " policyQualifierInfos=" + policyQualifierInfos + " ]";
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/x509/ext/ExtendedKeyUsage.java b/libjava/classpath/gnu/java/security/x509/ext/ExtendedKeyUsage.java
new file mode 100644
index 00000000000..37b08acf43e
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/ext/ExtendedKeyUsage.java
@@ -0,0 +1,95 @@
+/* ExtendedKeyUsage.java -- the extended key usage extension.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.x509.ext;
+
+import gnu.java.security.OID;
+import gnu.java.security.der.DER;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+public class ExtendedKeyUsage extends Extension.Value
+{
+
+ // Constants and fields.
+ // -------------------------------------------------------------------------
+
+ public static final OID ID = new OID("2.5.29.37");
+
+ private final List purposeIds;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public ExtendedKeyUsage(final byte[] encoded) throws IOException
+ {
+ super(encoded);
+ DERReader der = new DERReader(encoded);
+ DERValue usageList = der.read();
+ if (!usageList.isConstructed())
+ throw new IOException("malformed ExtKeyUsageSyntax");
+ int len = 0;
+ purposeIds = new LinkedList();
+ while (len < usageList.getLength())
+ {
+ DERValue val = der.read();
+ if (val.getTag() != DER.OBJECT_IDENTIFIER)
+ throw new IOException("malformed KeyPurposeId");
+ purposeIds.add(val.getValue());
+ len += val.getEncodedLength();
+ }
+ }
+
+ // Instance method.
+ // -------------------------------------------------------------------------
+
+ public List getPurposeIds()
+ {
+ return Collections.unmodifiableList(purposeIds);
+ }
+
+ public String toString()
+ {
+ return ExtendedKeyUsage.class.getName() + " [ " + purposeIds + " ]";
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/x509/ext/Extension.java b/libjava/classpath/gnu/java/security/x509/ext/Extension.java
new file mode 100644
index 00000000000..5ca9ac3a91d
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/ext/Extension.java
@@ -0,0 +1,289 @@
+/* Extension.java -- an X.509 certificate or CRL extension.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.x509.ext;
+
+import gnu.java.security.OID;
+import gnu.java.security.der.DER;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+import gnu.java.security.x509.Util;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class Extension
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ private static final boolean DEBUG = false;
+ private static void debug(String msg)
+ {
+ System.err.print(">> Extension: ");
+ System.err.println(msg);
+ }
+
+ /**
+ * This extension's object identifier.
+ */
+ protected final OID oid;
+
+ /**
+ * The criticality flag.
+ */
+ protected final boolean critical;
+
+ /**
+ * Whether or not this extension is locally supported.
+ */
+ protected boolean isSupported;
+
+ /**
+ * The extension value.
+ */
+ protected final Value value;
+
+ /**
+ * The DER encoded form.
+ */
+ protected byte[] encoded;
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ public Extension(byte[] encoded) throws IOException
+ {
+ this.encoded = (byte[]) encoded.clone();
+ DERReader der = new DERReader(encoded);
+
+ // Extension ::= SEQUENCE {
+ DERValue val = der.read();
+ if (DEBUG) debug("read val tag == " + val.getTag() + " len == " + val.getLength());
+ if (!val.isConstructed())
+ throw new IOException("malformed Extension");
+
+ // extnID OBJECT IDENTIFIER,
+ val = der.read();
+ if (val.getTag() != DER.OBJECT_IDENTIFIER)
+ throw new IOException("expecting OBJECT IDENTIFIER");
+ oid = (OID) val.getValue();
+ if (DEBUG) debug("read oid == " + oid);
+
+ // critical BOOLEAN DEFAULT FALSE,
+ val = der.read();
+ if (val.getTag() == DER.BOOLEAN)
+ {
+ critical = ((Boolean) val.getValue()).booleanValue();
+ val = der.read();
+ }
+ else
+ critical = false;
+ if (DEBUG) debug("is critical == " + critical);
+
+ // extnValue OCTET STRING }
+ if (val.getTag() != DER.OCTET_STRING)
+ throw new IOException("expecting OCTET STRING");
+ byte[] encval = (byte[]) val.getValue();
+ isSupported = true;
+ if (oid.equals(AuthorityKeyIdentifier.ID))
+ {
+ value = new AuthorityKeyIdentifier(encval);
+ }
+ else if (oid.equals(SubjectKeyIdentifier.ID))
+ {
+ value = new SubjectKeyIdentifier(encval);
+ }
+ else if (oid.equals(KeyUsage.ID))
+ {
+ value = new KeyUsage(encval);
+ }
+ else if (oid.equals(PrivateKeyUsagePeriod.ID))
+ {
+ value = new PrivateKeyUsagePeriod(encval);
+ }
+ else if (oid.equals(CertificatePolicies.ID))
+ {
+ value = new CertificatePolicies(encval);
+ }
+ else if (oid.equals (PolicyConstraint.ID))
+ {
+ value = new PolicyConstraint (encval);
+ }
+ else if (oid.equals(PolicyMappings.ID))
+ {
+ value = new PolicyMappings(encval);
+ }
+ else if (oid.equals(SubjectAlternativeNames.ID))
+ {
+ value = new SubjectAlternativeNames(encval);
+ }
+ else if (oid.equals(IssuerAlternativeNames.ID))
+ {
+ value = new IssuerAlternativeNames(encval);
+ }
+ else if (oid.equals(BasicConstraints.ID))
+ {
+ value = new BasicConstraints(encval);
+ }
+ else if (oid.equals(ExtendedKeyUsage.ID))
+ {
+ value = new ExtendedKeyUsage(encval);
+ }
+ else if (oid.equals(CRLNumber.ID))
+ {
+ value = new CRLNumber(encval);
+ }
+ else if (oid.equals(ReasonCode.ID))
+ {
+ value = new ReasonCode(encval);
+ }
+ else
+ {
+ value = new Value(encval);
+ isSupported = false;
+ }
+ if (DEBUG) debug("read value == " + value);
+ }
+
+ public Extension (final OID oid, final Value value, final boolean critical)
+ {
+ this.oid = oid;
+ this.value = value;
+ this.critical = critical;
+ isSupported = true;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public OID getOid()
+ {
+ return oid;
+ }
+
+ public boolean isCritical()
+ {
+ return critical;
+ }
+
+ public boolean isSupported()
+ {
+ return isSupported;
+ }
+
+ public Value getValue()
+ {
+ return value;
+ }
+
+ public byte[] getEncoded()
+ {
+ if (encoded == null)
+ encode();
+ return (byte[]) encoded.clone();
+ }
+
+ public String toString()
+ {
+ return Extension.class.getName() + " [ id=" + oid + " critical=" +
+ critical + " value=" + value + " ]";
+ }
+
+ public DERValue getDerValue()
+ {
+ List ext = new ArrayList (3);
+ ext.add (new DERValue (DER.OBJECT_IDENTIFIER, oid));
+ ext.add (new DERValue (DER.BOOLEAN, new Boolean (critical)));
+ ext.add (new DERValue (DER.OCTET_STRING, value.getEncoded()));
+ return new DERValue (DER.CONSTRUCTED|DER.SEQUENCE, ext);
+ }
+
+ // Own methods.
+ // -------------------------------------------------------------------------
+
+ private void encode()
+ {
+ encoded = getDerValue().getEncoded();
+ }
+
+ // Inner class.
+ // -------------------------------------------------------------------------
+
+ public static class Value
+ {
+
+ // Fields.
+ // -----------------------------------------------------------------------
+
+ protected byte[] encoded;
+
+ // Constructor.
+ // -----------------------------------------------------------------------
+
+ public Value(byte[] encoded)
+ {
+ this.encoded = (byte[]) encoded.clone();
+ }
+
+ protected Value() { }
+
+ // Instance methods.
+ // -----------------------------------------------------------------------
+
+ public byte[] getEncoded()
+ {
+ return (byte[]) encoded;
+ }
+
+ public boolean equals(Object o)
+ {
+ if (!(o instanceof Value))
+ return false;
+ return Arrays.equals(encoded, ((Value) o).encoded);
+ }
+
+ public String toString()
+ {
+ return Util.toHexString(encoded, ':');
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/x509/ext/GeneralNames.java b/libjava/classpath/gnu/java/security/x509/ext/GeneralNames.java
new file mode 100644
index 00000000000..e92aedaefd0
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/ext/GeneralNames.java
@@ -0,0 +1,155 @@
+/* GeneralNames.java -- the GeneralNames object
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.x509.ext;
+
+import gnu.java.security.OID;
+import gnu.java.security.der.DER;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+import gnu.java.security.x509.X500DistinguishedName;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+public class GeneralNames
+{
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public static final int OTHER_NAME = 0;
+ public static final int RFC822_NAME = 1;
+ public static final int DNS_NAME = 2;
+ public static final int X400_ADDRESS = 3;
+ public static final int DIRECTORY_NAME = 4;
+ public static final int EDI_PARTY_NAME = 5;
+ public static final int URI = 6;
+ public static final int IP_ADDRESS = 7;
+ public static final int REGISTERED_ID = 8;
+
+ private List names;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public GeneralNames(final byte[] encoded) throws IOException
+ {
+ names = new LinkedList();
+ DERReader der = new DERReader(encoded);
+ DERValue nameList = der.read();
+ if (!nameList.isConstructed())
+ throw new IOException("malformed GeneralNames");
+ int len = 0;
+ while (len < nameList.getLength())
+ {
+ DERValue name = der.read();
+ List namePair = new ArrayList(2);
+ if (name.getTagClass() != DER.APPLICATION)
+ throw new IOException("malformed GeneralName");
+ namePair.add(new Integer(name.getTag()));
+ DERValue val = null;
+ switch (name.getTag())
+ {
+ case RFC822_NAME:
+ case DNS_NAME:
+ case X400_ADDRESS:
+ case URI:
+ namePair.add(new String((byte[]) name.getValue()));
+ break;
+
+ case OTHER_NAME:
+ case EDI_PARTY_NAME:
+ namePair.add(name.getValue());
+ break;
+
+ case DIRECTORY_NAME:
+ byte[] b = name.getEncoded();
+ b[0] = (byte) (DER.CONSTRUCTED|DER.SEQUENCE);
+ namePair.add(new X500DistinguishedName(b).toString());
+ break;
+
+ case IP_ADDRESS:
+ namePair.add(InetAddress.getByAddress((byte[]) name.getValue())
+ .getHostAddress());
+ break;
+
+ case REGISTERED_ID:
+ byte[] bb = name.getEncoded();
+ bb[0] = (byte) DER.OBJECT_IDENTIFIER;
+ namePair.add(new OID(bb).toString());
+ break;
+
+ default:
+ throw new IOException("unknown tag " + name.getTag());
+ }
+ names.add(namePair);
+ len += name.getEncodedLength();
+ }
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public List getNames()
+ {
+ List l = new ArrayList(names.size());
+ for (Iterator it = names.iterator(); it.hasNext(); )
+ {
+ List ll = (List) it.next();
+ List pair = new ArrayList(2);
+ pair.add(ll.get(0));
+ if (ll.get(1) instanceof byte[])
+ pair.add(((byte[]) ll.get(1)).clone());
+ else
+ pair.add(ll.get(1));
+ l.add(Collections.unmodifiableList(pair));
+ }
+ return Collections.unmodifiableList(l);
+ }
+
+ public String toString()
+ {
+ return GeneralNames.class.getName() + " [ " + names + " ]";
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/x509/ext/IssuerAlternativeNames.java b/libjava/classpath/gnu/java/security/x509/ext/IssuerAlternativeNames.java
new file mode 100644
index 00000000000..8b017dc62d8
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/ext/IssuerAlternativeNames.java
@@ -0,0 +1,77 @@
+/* IssuerAlternatuveNames.java -- issuer alternative names extension.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.x509.ext;
+
+import gnu.java.security.OID;
+
+import java.io.IOException;
+import java.util.List;
+
+public class IssuerAlternativeNames extends Extension.Value
+{
+
+ // Constants and fields.
+ // -------------------------------------------------------------------------
+
+ public static final OID ID = new OID("2.5.29.18");
+
+ private final GeneralNames names;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public IssuerAlternativeNames(final byte[] encoded) throws IOException
+ {
+ super(encoded);
+ names = new GeneralNames(encoded);
+ }
+
+ // Instance method.
+ // -------------------------------------------------------------------------
+
+ public List getNames()
+ {
+ return names.getNames();
+ }
+
+ public String toString()
+ {
+ return IssuerAlternativeNames.class.getName() + " [ " + names + " ]";
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/x509/ext/KeyUsage.java b/libjava/classpath/gnu/java/security/x509/ext/KeyUsage.java
new file mode 100644
index 00000000000..dcd98181e12
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/ext/KeyUsage.java
@@ -0,0 +1,92 @@
+/* KeyUsage.java -- the key usage extension.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.x509.ext;
+
+import gnu.java.security.OID;
+import gnu.java.security.der.BitString;
+import gnu.java.security.der.DER;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+
+import java.io.IOException;
+
+public class KeyUsage extends Extension.Value
+{
+
+ // Constants and fields.
+ // -------------------------------------------------------------------------
+
+ public static final OID ID = new OID("2.5.29.15");
+ public static final int DIGITAL_SIGNATURE = 0;
+ public static final int NON_REPUDIATION = 1;
+ public static final int KEY_ENCIPHERMENT = 2;
+ public static final int DATA_ENCIPHERMENT = 3;
+ public static final int KEY_AGREEMENT = 4;
+ public static final int KEY_CERT_SIGN = 5;
+ public static final int CRL_SIGN = 6;
+ public static final int ENCIPHER_ONLY = 7;
+ public static final int DECIPHER_ONLY = 8;
+
+ private final BitString keyUsage;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public KeyUsage(final byte[] encoded) throws IOException
+ {
+ super(encoded);
+ DERValue val = DERReader.read(encoded);
+ if (val.getTag() != DER.BIT_STRING)
+ throw new IOException("malformed KeyUsage");
+ keyUsage = (BitString) val.getValue();
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public BitString getKeyUsage()
+ {
+ return keyUsage;
+ }
+
+ public String toString()
+ {
+ return KeyUsage.class.getName() + " [ " + keyUsage + " ]";
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/x509/ext/PolicyConstraint.java b/libjava/classpath/gnu/java/security/x509/ext/PolicyConstraint.java
new file mode 100644
index 00000000000..20cf552a0fe
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/ext/PolicyConstraint.java
@@ -0,0 +1,107 @@
+/* PolicyConstraint.java -- policyConstraint extension
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.x509.ext;
+
+import gnu.java.security.OID;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+
+import java.io.IOException;
+import java.math.BigInteger;
+
+public class PolicyConstraint extends Extension.Value
+{
+
+ // Constants and fields.
+ // -------------------------------------------------------------------------
+
+ public static final OID ID = new OID ("2.5.29.36");
+
+ private final int requireExplicitPolicy;
+ private final int inhibitPolicyMapping;
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ public PolicyConstraint (final byte[] encoded) throws IOException
+ {
+ super (encoded);
+ int rpc = -1, ipm = -1;
+ DERReader der = new DERReader(encoded);
+ DERValue pc = der.read();
+ if (!pc.isConstructed())
+ throw new IOException("malformed PolicyConstraints");
+ DERValue val;
+ int len = pc.getLength();
+ while (len > 0)
+ {
+ val = der.read();
+ if (val.getTag() == 0)
+ rpc = new BigInteger ((byte[]) val.getValue()).intValue();
+ else if (val.getTag() == 1)
+ ipm = new BigInteger ((byte[]) val.getValue()).intValue();
+ else
+ throw new IOException ("invalid policy constraint");
+ len -= val.getEncodedLength();
+ }
+
+ requireExplicitPolicy = rpc;
+ inhibitPolicyMapping = ipm;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public int getRequireExplicitPolicy()
+ {
+ return requireExplicitPolicy;
+ }
+
+ public int getInhibitPolicyMapping()
+ {
+ return inhibitPolicyMapping;
+ }
+
+ public String toString()
+ {
+ return PolicyConstraint.class.getName() + " [ requireExplicitPolicy=" +
+ requireExplicitPolicy + " inhibitPolicyMapping=" + inhibitPolicyMapping
+ + " ]";
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/x509/ext/PolicyMappings.java b/libjava/classpath/gnu/java/security/x509/ext/PolicyMappings.java
new file mode 100644
index 00000000000..0493ed89dd4
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/ext/PolicyMappings.java
@@ -0,0 +1,104 @@
+/* PolicyMappings.java -- policy mappings extension.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.x509.ext;
+
+import gnu.java.security.OID;
+import gnu.java.security.der.DER;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public class PolicyMappings extends Extension.Value
+{
+
+ // Constants and fields.
+ // -------------------------------------------------------------------------
+
+ public static final OID ID = new OID("2.5.29.33");
+
+ private final Map mappings;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public PolicyMappings(final byte[] encoded) throws IOException
+ {
+ super(encoded);
+ DERReader der = new DERReader(encoded);
+ DERValue maps = der.read();
+ if (!maps.isConstructed())
+ throw new IOException("malformed PolicyMappings");
+ int len = 0;
+ HashMap _mappings = new HashMap();
+ while (len < maps.getLength())
+ {
+ DERValue map = der.read();
+ if (!map.isConstructed())
+ throw new IOException("malformed PolicyMapping");
+ DERValue val = der.read();
+ if (val.getTag() != DER.OBJECT_IDENTIFIER)
+ throw new IOException("malformed PolicyMapping");
+ OID issuerPolicy = (OID) val.getValue();
+ val = der.read();
+ if (val.getTag() != DER.OBJECT_IDENTIFIER)
+ throw new IOException("malformed PolicyMapping");
+ OID subjectPolicy = (OID) val.getValue();
+ _mappings.put(issuerPolicy, subjectPolicy);
+ len += map.getEncodedLength();
+ }
+ mappings = Collections.unmodifiableMap(_mappings);
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public OID getSubjectDomainPolicy(OID issuerDomainPolicy)
+ {
+ return (OID) mappings.get(issuerDomainPolicy);
+ }
+
+ public String toString()
+ {
+ return PolicyMappings.class.getName() + " [ " + mappings + " ]";
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/x509/ext/PrivateKeyUsagePeriod.java b/libjava/classpath/gnu/java/security/x509/ext/PrivateKeyUsagePeriod.java
new file mode 100644
index 00000000000..3b531c05517
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/ext/PrivateKeyUsagePeriod.java
@@ -0,0 +1,105 @@
+/* PrivateKeyUsagePeriod.java -- private key usage period extension.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.x509.ext;
+
+import gnu.java.security.OID;
+import gnu.java.security.der.DER;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+
+import java.io.IOException;
+import java.util.Date;
+
+public class PrivateKeyUsagePeriod extends Extension.Value
+{
+
+ // Constants and fields.
+ // -------------------------------------------------------------------------
+
+ public static final OID ID = new OID("2.5.29.16");
+
+ private final Date notBefore;
+ private final Date notAfter;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public PrivateKeyUsagePeriod(final byte[] encoded) throws IOException
+ {
+ super(encoded);
+ DERReader der = new DERReader(encoded);
+ DERValue val = der.read();
+ if (!val.isConstructed())
+ throw new IOException("malformed PrivateKeyUsagePeriod");
+ if (val.getLength() > 0)
+ val = der.read();
+ if (val.getTagClass() == DER.APPLICATION || val.getTag() == 0)
+ {
+ notBefore = (Date) val.getValueAs (DER.GENERALIZED_TIME);
+ val = der.read();
+ }
+ else
+ notBefore = null;
+ if (val.getTagClass() == DER.APPLICATION || val.getTag() == 1)
+ {
+ notAfter = (Date) val.getValueAs (DER.GENERALIZED_TIME);
+ }
+ else
+ notAfter = null;
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public Date getNotBefore()
+ {
+ return notBefore != null ? (Date) notBefore.clone() : null;
+ }
+
+ public Date getNotAfter()
+ {
+ return notAfter != null ? (Date) notAfter.clone() : null;
+ }
+
+ public String toString()
+ {
+ return PrivateKeyUsagePeriod.class.getName() + " [ notBefore=" + notBefore
+ + " notAfter=" + notAfter + " ]";
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/x509/ext/ReasonCode.java b/libjava/classpath/gnu/java/security/x509/ext/ReasonCode.java
new file mode 100644
index 00000000000..a6d59e43ae8
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/ext/ReasonCode.java
@@ -0,0 +1,85 @@
+/* ReasonCode.java -- a reason code for a certificate revocation.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.x509.ext;
+
+import gnu.java.security.OID;
+import gnu.java.security.der.DER;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+
+import java.io.IOException;
+import java.math.BigInteger;
+
+public class ReasonCode extends Extension.Value
+{
+
+ // Constants and fields.
+ // -------------------------------------------------------------------------
+
+ public static final OID ID = new OID("2.5.29.21");
+
+ public final int reason;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public ReasonCode(final byte[] encoded) throws IOException
+ {
+ super(encoded);
+ DERValue val = DERReader.read(encoded);
+ if (val.getTag() != DER.ENUMERATED)
+ throw new IOException("malformed CRLReason");
+ reason = ((BigInteger) val.getValue()).intValue();
+ if (reason < 0 || reason == 7 || reason > 10)
+ throw new IOException("illegal reason: " + reason);
+ }
+
+ // Instance method.
+ // -------------------------------------------------------------------------
+
+ public int getReasonCode()
+ {
+ return reason;
+ }
+
+ public String toString()
+ {
+ return ReasonCode.class.getName() + " [ " + reason + " ]";
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/x509/ext/SubjectAlternativeNames.java b/libjava/classpath/gnu/java/security/x509/ext/SubjectAlternativeNames.java
new file mode 100644
index 00000000000..f88e854965f
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/ext/SubjectAlternativeNames.java
@@ -0,0 +1,77 @@
+/* SubjectAlternatuveNames.java -- subject alternative names extension.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.x509.ext;
+
+import gnu.java.security.OID;
+
+import java.io.IOException;
+import java.util.List;
+
+public class SubjectAlternativeNames extends Extension.Value
+{
+
+ // Constants and fields.
+ // -------------------------------------------------------------------------
+
+ public static final OID ID = new OID("2.5.29.17");
+
+ private final GeneralNames names;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public SubjectAlternativeNames(final byte[] encoded) throws IOException
+ {
+ super(encoded);
+ names = new GeneralNames(encoded);
+ }
+
+ // Instance method.
+ // -------------------------------------------------------------------------
+
+ public List getNames()
+ {
+ return names.getNames();
+ }
+
+ public String toString()
+ {
+ return SubjectAlternativeNames.class.getName() + " [ " + names + " ]";
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/x509/ext/SubjectKeyIdentifier.java b/libjava/classpath/gnu/java/security/x509/ext/SubjectKeyIdentifier.java
new file mode 100644
index 00000000000..fc65abe211c
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/ext/SubjectKeyIdentifier.java
@@ -0,0 +1,84 @@
+/* SubjectKeyIdentifier.java -- subject key identifier extension.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.x509.ext;
+
+import gnu.java.security.OID;
+import gnu.java.security.der.DER;
+import gnu.java.security.der.DERReader;
+import gnu.java.security.der.DERValue;
+import gnu.java.security.x509.Util;
+
+import java.io.IOException;
+
+public class SubjectKeyIdentifier extends Extension.Value
+{
+
+ // Constant.
+ // -------------------------------------------------------------------------
+
+ public static final OID ID = new OID("2.5.29.14");
+
+ private final byte[] keyIdentifier;
+
+ // Constructor.
+ // -------------------------------------------------------------------------
+
+ public SubjectKeyIdentifier(final byte[] encoded) throws IOException
+ {
+ super(encoded);
+ DERValue val = DERReader.read(encoded);
+ if (val.getTag() != DER.OCTET_STRING)
+ throw new IOException("malformed SubjectKeyIdentifier");
+ keyIdentifier = (byte[]) val.getValue();
+ }
+
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public byte[] getKeyIdentifier()
+ {
+ return (byte[]) keyIdentifier.clone();
+ }
+
+ public String toString()
+ {
+ return SubjectKeyIdentifier.class.getName() + " [ " +
+ Util.toHexString (keyIdentifier, ':') + " ]";
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/x509/ext/package.html b/libjava/classpath/gnu/java/security/x509/ext/package.html
new file mode 100644
index 00000000000..cc44e55c97e
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/ext/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in gnu.java.security.x509.ext package.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - gnu.java.security.x509.ext</title></head>
+
+<body>
+<p></p>
+
+</body>
+</html>
diff --git a/libjava/classpath/gnu/java/security/x509/package.html b/libjava/classpath/gnu/java/security/x509/package.html
new file mode 100644
index 00000000000..8b0ba008451
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/x509/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in gnu.java.security.x509 package.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - gnu.java.security.x509</title></head>
+
+<body>
+<p></p>
+
+</body>
+</html>
OpenPOWER on IntegriCloud