summaryrefslogtreecommitdiff
path: root/libjava/classpath/gnu/java/security/pkcs
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/gnu/java/security/pkcs')
-rw-r--r--libjava/classpath/gnu/java/security/pkcs/PKCS7Data.java69
-rw-r--r--libjava/classpath/gnu/java/security/pkcs/PKCS7SignedData.java485
-rw-r--r--libjava/classpath/gnu/java/security/pkcs/SignerInfo.java429
-rw-r--r--libjava/classpath/gnu/java/security/pkcs/package.html46
4 files changed, 1029 insertions, 0 deletions
diff --git a/libjava/classpath/gnu/java/security/pkcs/PKCS7Data.java b/libjava/classpath/gnu/java/security/pkcs/PKCS7Data.java
new file mode 100644
index 000000000..c6474f081
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/pkcs/PKCS7Data.java
@@ -0,0 +1,69 @@
+/* PKCS7Data.java -- Reader/writer for PKCS#7 Data objects
+ Copyright (C) 2006 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.pkcs;
+
+import gnu.java.security.OID;
+
+/**
+ * A read/write helper class for PKCS#7 Data ASN.1 structures.
+ */
+public class PKCS7Data
+{
+ public static final OID PKCS7_DATA = new OID("1.2.840.113549.1.7.1");
+
+ private byte[] content;
+
+ /**
+ * Constructs a new instance of <code>PKCS7Data</code> with the possibly
+ * null (implicetly referenced) content data.
+ *
+ * @param data the raw bytes of the data to use in a PKCS#7 framework.
+ */
+ public PKCS7Data(byte[] data)
+ {
+ super();
+
+ this.content = data;
+ }
+
+ public byte[] getEncoded()
+ {
+ return content;
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/pkcs/PKCS7SignedData.java b/libjava/classpath/gnu/java/security/pkcs/PKCS7SignedData.java
new file mode 100644
index 000000000..adb00a3be
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/pkcs/PKCS7SignedData.java
@@ -0,0 +1,485 @@
+/* PKCS7SignedData.java -- reader/writer for PKCS#7 signedData objects
+ Copyright (C) 2004, 2005, 2006 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.pkcs;
+
+import gnu.java.security.Configuration;
+import gnu.java.security.OID;
+import gnu.java.security.ber.BER;
+import gnu.java.security.ber.BEREncodingException;
+import gnu.java.security.ber.BERReader;
+import gnu.java.security.ber.BERValue;
+import gnu.java.security.der.DER;
+import gnu.java.security.der.DERValue;
+import gnu.java.security.der.DERWriter;
+import gnu.java.security.util.Util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.security.cert.CRL;
+import java.security.cert.CRLException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509CRL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Logger;
+
+/**
+ * The SignedData object in PKCS #7. This is a read-only implementation of
+ * this format, and is used to provide signed Jar file support.
+ *
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class PKCS7SignedData
+{
+ private static final Logger log = Logger.getLogger(PKCS7SignedData.class.getName());
+
+ public static final OID PKCS7_SIGNED_DATA = new OID("1.2.840.113549.1.7.2");
+
+ private BigInteger version;
+ private Set digestAlgorithms;
+ private OID contentType;
+ private byte[] content;
+ private Certificate[] certificates;
+ private CRL[] crls;
+ private Set signerInfos;
+
+ public PKCS7SignedData(InputStream in)
+ throws CRLException, CertificateException, IOException
+ {
+ this(new BERReader(in));
+ }
+
+ /**
+ * Parse an encoded PKCS#7 SignedData object. The ASN.1 format of this
+ * object is:
+ *
+ * <pre>
+ * SignedData ::= SEQUENCE {
+ * version Version, -- always 1 for PKCS7 v1.5
+ * digestAlgorithms DigestAlgorithmIdentifiers,
+ * contentInfo ContentInfo,
+ * certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
+ * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+ * signerInfos SignerInfos }
+ *
+ * Version ::= INTEGER
+ *
+ * DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
+ *
+ * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+ *
+ * ContentInfo ::= SEQUENCE {
+ * contentType ContentType,
+ * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+ *
+ * ContentType ::= OBJECT IDENTIFIER
+ *
+ * ExtendedCertificatesAndCertificates ::=
+ * SET OF ExtendedCertificatesAndCertificate
+ *
+ * ExtendedCertificatesAndCertificate ::= CHOICE {
+ * certificate Certificate, -- from X.509
+ * extendedCertificate [0] IMPLICIT ExtendedCertificate }
+ *
+ * CertificateRevocationLists ::= SET OF CertificateRevocationList
+ * -- from X.509
+ *
+ * SignerInfos ::= SET OF SignerInfo
+ *
+ * SignerInfo ::= SEQUENCE {
+ * version Version, -- always 1 for PKCS7 v1.5
+ * issuerAndSerialNumber IssuerAndSerialNumber,
+ * digestAlgorithm DigestAlgorithmIdentifier,
+ * authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
+ * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
+ * encryptedDigest EncryptedDigest,
+ * unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL }
+ *
+ * EncryptedDigest ::= OCTET STRING
+ * </pre>
+ *
+ * <p>(Readers who are confused as to why it takes 40 levels of indirection
+ * to specify "data with a signature", rest assured that the present author
+ * is as confused as you are).</p>
+ */
+ public PKCS7SignedData(BERReader ber)
+ throws CRLException, CertificateException, IOException
+ {
+ CertificateFactory x509 = CertificateFactory.getInstance("X509");
+ DERValue val = ber.read();
+ if (!val.isConstructed())
+ throw new BEREncodingException("malformed ContentInfo");
+
+ val = ber.read();
+ if (val.getTag() != BER.OBJECT_IDENTIFIER)
+ throw new BEREncodingException("malformed ContentType");
+
+ if (!PKCS7_SIGNED_DATA.equals(val.getValue()))
+ throw new BEREncodingException("content is not SignedData");
+
+ val = ber.read();
+ if (val.getTag() != 0)
+ throw new BEREncodingException("malformed Content");
+
+ val = ber.read();
+ if (!val.isConstructed())
+ throw new BEREncodingException("malformed SignedData");
+
+ if (Configuration.DEBUG)
+ log.fine("SignedData: " + val);
+
+ val = ber.read();
+ if (val.getTag() != BER.INTEGER)
+ throw new BEREncodingException("expecting Version");
+ version = (BigInteger) val.getValue();
+ if (Configuration.DEBUG)
+ log.fine(" Version: " + version);
+
+ digestAlgorithms = new HashSet();
+ val = ber.read();
+ if (!val.isConstructed())
+ throw new BEREncodingException("malformed DigestAlgorithmIdentifiers");
+ if (Configuration.DEBUG)
+ log.fine(" DigestAlgorithmIdentifiers: " + val);
+ int count = 0;
+ DERValue val2 = ber.read();
+ while (val2 != BER.END_OF_SEQUENCE &&
+ (val.getLength() > 0 && val.getLength() > count))
+ {
+ if (!val2.isConstructed())
+ throw new BEREncodingException("malformed AlgorithmIdentifier");
+ if (Configuration.DEBUG)
+ log.fine(" AlgorithmIdentifier: " + val2);
+ count += val2.getEncodedLength();
+ val2 = ber.read();
+ if (val2.getTag() != BER.OBJECT_IDENTIFIER)
+ throw new BEREncodingException("malformed AlgorithmIdentifier");
+ if (Configuration.DEBUG)
+ log.fine(" digestAlgorithmIdentifiers OID: " + val2.getValue());
+ List algId = new ArrayList(2);
+ algId.add(val2.getValue());
+ val2 = ber.read();
+ if (val2 != BER.END_OF_SEQUENCE)
+ {
+ count += val2.getEncodedLength();
+ if (val2.getTag() == BER.NULL)
+ algId.add(null);
+ else
+ algId.add(val2.getEncoded());
+
+ if (val2.isConstructed())
+ ber.skip(val2.getLength());
+
+ if (BERValue.isIndefinite(val))
+ val2 = ber.read();
+ }
+ else
+ algId.add(null);
+
+ if (Configuration.DEBUG)
+ {
+ log.fine(" digestAlgorithmIdentifiers params: ");
+ log.fine(Util.dumpString((byte[]) algId.get(1),
+ " digestAlgorithmIdentifiers params: "));
+ }
+ digestAlgorithms.add(algId);
+ }
+
+ val = ber.read();
+ if (!val.isConstructed())
+ throw new BEREncodingException("malformed ContentInfo");
+ if (Configuration.DEBUG)
+ log.fine(" ContentInfo: " + val);
+ val2 = ber.read();
+ if (val2.getTag() != BER.OBJECT_IDENTIFIER)
+ throw new BEREncodingException("malformed ContentType");
+
+ contentType = (OID) val2.getValue();
+ if (Configuration.DEBUG)
+ log.fine(" ContentType OID: " + contentType);
+ if (BERValue.isIndefinite(val)
+ || (val.getLength() > 0 && val.getLength() > val2.getEncodedLength()))
+ {
+ val2 = ber.read();
+ if (val2 != BER.END_OF_SEQUENCE)
+ {
+ content = val2.getEncoded();
+ if (BERValue.isIndefinite(val))
+ val2 = ber.read();
+ }
+ }
+ if (Configuration.DEBUG)
+ {
+ log.fine(" Content: ");
+ log.fine(Util.dumpString(content, " Content: "));
+ }
+ val = ber.read();
+ if (val.getTag() == 0)
+ {
+ if (!val.isConstructed())
+ throw new BEREncodingException("malformed ExtendedCertificatesAndCertificates");
+ if (Configuration.DEBUG)
+ log.fine(" ExtendedCertificatesAndCertificates: " + val);
+ count = 0;
+ val2 = ber.read();
+ List certs = new LinkedList();
+ while (val2 != BER.END_OF_SEQUENCE &&
+ (val.getLength() > 0 && val.getLength() > count))
+ {
+ Certificate cert =
+ x509.generateCertificate(new ByteArrayInputStream(val2.getEncoded()));
+ if (Configuration.DEBUG)
+ log.fine(" Certificate: " + cert);
+ certs.add(cert);
+ count += val2.getEncodedLength();
+ ber.skip(val2.getLength());
+ if (BERValue.isIndefinite(val) || val.getLength() > count)
+ val2 = ber.read();
+ }
+ certificates = (Certificate[]) certs.toArray(new Certificate[certs.size()]);
+ val = ber.read();
+ }
+
+ if (val.getTag() == 1)
+ {
+ if (!val.isConstructed())
+ throw new BEREncodingException("malformed CertificateRevocationLists");
+ if (Configuration.DEBUG)
+ log.fine(" CertificateRevocationLists: " + val);
+ count = 0;
+ val2 = ber.read();
+ List crls = new LinkedList();
+ while (val2 != BER.END_OF_SEQUENCE &&
+ (val.getLength() > 0 && val.getLength() > count))
+ {
+ CRL crl = x509.generateCRL(new ByteArrayInputStream(val2.getEncoded()));
+ if (Configuration.DEBUG)
+ log.fine(" CRL: " + crl);
+ crls.add(crl);
+ count += val2.getEncodedLength();
+ ber.skip(val2.getLength());
+ if (BERValue.isIndefinite(val) || val.getLength() > count)
+ val2 = ber.read();
+ }
+ this.crls = (CRL[]) crls.toArray(new CRL[crls.size()]);
+ val = ber.read();
+ }
+
+ signerInfos = new HashSet();
+ if (!val.isConstructed())
+ throw new BEREncodingException("malformed SignerInfos");
+ if (Configuration.DEBUG)
+ log.fine(" SignerInfos: " + val);
+
+ // FIXME read this more carefully.
+ // Since we are just reading a file (probably) we just read until we
+ // reach the end.
+ while (true)
+ {
+ int i = ber.peek();
+ if (i == 0 || i == -1)
+ break;
+ signerInfos.add(new SignerInfo(ber));
+ }
+ }
+
+ /**
+ * Constructs a new instance of <code>PKCS7SignedData</code> given a
+ * designated set of fields.
+ *
+ * @param digestAlgorithms the collection of DigestAlgorithm elements. Each
+ * DigestAlgorithm is a {@link List} of two elements, the first is an
+ * OID while the second is dependent on the value of the OID element.
+ * @param data an instance of a PKCS#7 (non-signed) data. In its simplest form
+ * such an ASN.1 structure would consist of just the OID of a
+ * non-signed PKCS#7 Data.
+ * @param certificates the array of Certificates used to authenticate the
+ * enclosed (or referenced, in case the content is null) data.
+ * @param crls the array of certificate-revocation lists of the used
+ * certificates.
+ * @param signerInfos a set of {@link SignerInfo} elements, one per signer of
+ * the data referenced by this <code>PKCS7SignedData</code>
+ * instance.
+ */
+ public PKCS7SignedData(Set digestAlgorithms, PKCS7Data data,
+ Certificate[] certificates, X509CRL[] crls,
+ Set signerInfos)
+ {
+ super();
+
+ this.version = BigInteger.ONE;
+ this.digestAlgorithms = digestAlgorithms;
+ this.contentType = PKCS7_SIGNED_DATA;
+ this.content = data == null ? null : data.getEncoded();
+ this.certificates = certificates;
+ this.crls = crls;
+ this.signerInfos = signerInfos;
+ }
+
+ public BigInteger getVersion()
+ {
+ return version;
+ }
+
+ public Certificate[] getCertificates()
+ {
+ return (certificates != null ? (Certificate[]) certificates.clone()
+ : null);
+ }
+
+ public OID getContentType()
+ {
+ return contentType;
+ }
+
+ public byte[] getContent()
+ {
+ return (content != null ? (byte[]) content.clone() : null);
+ }
+
+ public Set getDigestAlgorithms()
+ {
+ // FIXME copy contents too, they are mutable!!!
+ return Collections.unmodifiableSet(digestAlgorithms);
+ }
+
+ public Set getSignerInfos()
+ {
+ Set copy = new HashSet();
+ for (Iterator it = signerInfos.iterator(); it.hasNext(); )
+ copy.add(it.next());
+ return Collections.unmodifiableSet(copy);
+ }
+
+ /**
+ * Writes to the designated output stream the DER encoding of the current
+ * contents of this instance.
+ *
+ * @param out the destination output stream.
+ * @throws IOException if an I/O related exception occurs during the process.
+ * @throws CRLException if an exception occurs while encoding the certificate
+ * revocation lists associated with this instance.
+ * @throws CertificateEncodingException if an exception occurs while encoding
+ * the certificate chains associated with this instance.
+ */
+ public void encode(OutputStream out) throws IOException, CRLException,
+ CertificateEncodingException
+ {
+ DERValue derVersion = new DERValue(DER.INTEGER, version);
+
+ DERValue derDigestAlgorithms = new DERValue(DER.CONSTRUCTED | DER.SET,
+ digestAlgorithms);
+
+ DERValue derContentType = new DERValue(DER.OBJECT_IDENTIFIER,
+ PKCS7Data.PKCS7_DATA);
+ ArrayList contentInfo = new ArrayList(2);
+ contentInfo.add(derContentType);
+ if (content == null)
+ contentInfo.add(new DERValue(DER.NULL, null));
+ else
+ contentInfo.add(content);
+
+ DERValue derContentInfo = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
+ contentInfo);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
+ for (int i = 0; i < certificates.length; i++)
+ baos.write(certificates[i].getEncoded());
+
+ baos.flush();
+ byte[] b = baos.toByteArray();
+ DERValue derExtendedCertificatesAndCertificates =
+ new DERValue(DER.CONSTRUCTED | DER.CONTEXT | 0, b.length, b, null);
+
+ DERValue derCertificateRevocationLists = null;
+ if (crls != null && crls.length > 0)
+ {
+ baos.reset();
+ for (int i = 0; i < crls.length; i++)
+ baos.write(((X509CRL) crls[i]).getEncoded());
+
+ baos.flush();
+ byte[] b2 = baos.toByteArray();
+ derCertificateRevocationLists =
+ new DERValue(DER.CONSTRUCTED | DER.CONTEXT | 1, b2.length, b2, null);
+ }
+
+ baos.reset();
+ for (Iterator it = signerInfos.iterator(); it.hasNext();)
+ {
+ SignerInfo signerInfo = (SignerInfo) it.next();
+ signerInfo.encode(baos);
+ }
+ baos.flush();
+ byte[] b3 = baos.toByteArray();
+ DERValue derSignerInfos = new DERValue(DER.CONSTRUCTED | DER.SET,
+ b3.length, b3, null);
+
+ ArrayList signedData = new ArrayList(6);
+ signedData.add(derVersion);
+ signedData.add(derDigestAlgorithms);
+ signedData.add(derContentInfo);
+ signedData.add(derExtendedCertificatesAndCertificates);
+ if (derCertificateRevocationLists != null)
+ signedData.add(derCertificateRevocationLists);
+
+ signedData.add(derSignerInfos);
+ DERValue derSignedData = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
+ signedData);
+ // now the outer contents
+ ArrayList outer = new ArrayList(3);
+ outer.add(new DERValue(DER.OBJECT_IDENTIFIER, PKCS7_SIGNED_DATA));
+ outer.add(new DERValue(DER.CONTEXT | 0, null));
+ outer.add(derSignedData);
+ DERValue derOuter = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, outer);
+
+ DERWriter.write(out, derOuter);
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/pkcs/SignerInfo.java b/libjava/classpath/gnu/java/security/pkcs/SignerInfo.java
new file mode 100644
index 000000000..645ed67bb
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/pkcs/SignerInfo.java
@@ -0,0 +1,429 @@
+/* SignerInfo.java -- a SignerInfo object, from PKCS #7
+ Copyright (C) 2004, 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. */
+
+package gnu.java.security.pkcs;
+
+import gnu.java.security.Configuration;
+import gnu.java.security.OID;
+import gnu.java.security.ber.BER;
+import gnu.java.security.ber.BEREncodingException;
+import gnu.java.security.ber.BERReader;
+import gnu.java.security.ber.BERValue;
+import gnu.java.security.der.DER;
+import gnu.java.security.der.DERValue;
+import gnu.java.security.der.DERWriter;
+import gnu.java.security.util.Util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.logging.Logger;
+
+import javax.security.auth.x500.X500Principal;
+
+public class SignerInfo
+{
+ private static final Logger log = Logger.getLogger(SignerInfo.class.getName());
+
+ private final BigInteger version;
+ private final BigInteger serialNumber;
+ private final X500Principal issuer;
+ private final OID digestAlgorithmId;
+ private final byte[] digestAlgorithmParams;
+ private final byte[] authenticatedAttributes;
+ private final OID digestEncryptionAlgorithmId;
+ private final byte[] digestEncryptionAlgorithmParams;
+ private final byte[] encryptedDigest;
+ private final byte[] unauthenticatedAttributes;
+
+ /**
+ * Parse a SignerInfo object.
+ * <p>
+ * A SignerInfo is a structure with the following ASN.1 syntax:
+ * <pre>
+ * SignerInfo ::= SEQUENCE {
+ * version Version, -- always 1 for PKCS7 v1.5
+ * issuerAndSerialNumber IssuerAndSerialNumber, -- an INTEGER
+ * digestAlgorithm DigestAlgorithmIdentifier,
+ * authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
+ * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
+ * encryptedDigest EncryptedDigest,
+ * unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL }
+ *
+ * IssuerAndSerialNumber ::= SEQUENCE {
+ * issuer Name,
+ * serialNumber CertificateSerialNumber
+ * }
+ *
+ * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+ *
+ * DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+ *
+ * EncryptedDigest ::= OCTET STRING
+ * </pre>
+ */
+ public SignerInfo(BERReader ber) throws IOException
+ {
+ DERValue val = ber.read();
+ if (Configuration.DEBUG)
+ log.fine("SignerInfo: " + val);
+ if (!val.isConstructed())
+ throw new BEREncodingException("malformed SignerInfo");
+
+ val = ber.read();
+ if (val.getTag() != BER.INTEGER)
+ throw new BEREncodingException("malformed Version");
+
+ version = (BigInteger) val.getValue();
+ log.fine(" Version: " + version);
+
+ val = ber.read();
+ if (!val.isConstructed())
+ throw new BEREncodingException("malformed IssuerAndSerialNumber");
+ if (Configuration.DEBUG)
+ log.fine(" IssuerAndSerialNumber: " + val);
+
+ val = ber.read();
+ if (!val.isConstructed())
+ throw new BEREncodingException("malformed Issuer");
+
+ issuer = new X500Principal(val.getEncoded());
+ ber.skip(val.getLength());
+ if (Configuration.DEBUG)
+ log.fine(" Issuer: " + issuer);
+
+ val = ber.read();
+ if (val.getTag() != BER.INTEGER)
+ throw new BEREncodingException("malformed SerialNumber");
+
+ serialNumber = (BigInteger) val.getValue();
+ if (Configuration.DEBUG)
+ log.fine(" SerialNumber: " + serialNumber);
+
+ val = ber.read();
+ if (!val.isConstructed())
+ throw new BEREncodingException("malformed DigestAlgorithmIdentifier");
+ if (Configuration.DEBUG)
+ log.fine(" DigestAlgorithmIdentifier: " + val);
+
+ int count = 0;
+ DERValue val2 = ber.read();
+ if (val2.getTag() != BER.OBJECT_IDENTIFIER)
+ throw new BEREncodingException("malformed AlgorithmIdentifier");
+
+ digestAlgorithmId = (OID) val2.getValue();
+ if (Configuration.DEBUG)
+ log.fine(" digestAlgorithm OID: " + digestAlgorithmId);
+
+ if (BERValue.isIndefinite(val))
+ {
+ val2 = ber.read();
+ if (val2 != BER.END_OF_SEQUENCE)
+ {
+ digestAlgorithmParams = val2.getEncoded();
+ val2 = ber.read();
+ if (val2 != BER.END_OF_SEQUENCE)
+ throw new BEREncodingException("expecting BER end-of-sequence");
+ }
+ else
+ digestAlgorithmParams = null;
+ }
+ else if (val2.getEncodedLength() < val.getLength())
+ {
+ val2 = ber.read();
+ digestAlgorithmParams = val2.getEncoded();
+ if (val2.isConstructed())
+ ber.skip(val2.getLength());
+ }
+ else
+ digestAlgorithmParams = null;
+
+ if (Configuration.DEBUG)
+ {
+ log.fine(" digestAlgorithm params: ");
+ log.fine(Util.dumpString(digestAlgorithmParams,
+ " digestAlgorithm params: "));
+ }
+ val = ber.read();
+ if (val.getTag() == 0)
+ {
+ authenticatedAttributes = val.getEncoded();
+ val = ber.read();
+ if (val.isConstructed())
+ ber.skip(val.getLength());
+
+ val = ber.read();
+ }
+ else
+ authenticatedAttributes = null;
+
+ if (Configuration.DEBUG)
+ {
+ log.fine(" AuthenticatedAttributes: ");
+ log.fine(Util.dumpString(authenticatedAttributes,
+ " AuthenticatedAttributes: "));
+ }
+ if (!val.isConstructed())
+ throw new BEREncodingException("malformed DigestEncryptionAlgorithmIdentifier");
+ if (Configuration.DEBUG)
+ log.fine(" DigestEncryptionAlgorithmIdentifier: " + val);
+ count = 0;
+ val2 = ber.read();
+ if (val2.getTag() != BER.OBJECT_IDENTIFIER)
+ throw new BEREncodingException("malformed AlgorithmIdentifier");
+
+ digestEncryptionAlgorithmId = (OID) val2.getValue();
+ if (Configuration.DEBUG)
+ log.fine(" digestEncryptionAlgorithm OID: " + digestEncryptionAlgorithmId);
+
+ if (BERValue.isIndefinite(val))
+ {
+ val2 = ber.read();
+ if (val2 != BER.END_OF_SEQUENCE)
+ {
+ digestEncryptionAlgorithmParams = val2.getEncoded();
+ val2 = ber.read();
+ if (val2 != BER.END_OF_SEQUENCE)
+ throw new BEREncodingException("expecting BER end-of-sequence");
+ }
+ else
+ digestEncryptionAlgorithmParams = null;
+ }
+ else if (val2.getEncodedLength() < val.getLength())
+ {
+ val2 = ber.read();
+ digestEncryptionAlgorithmParams = val2.getEncoded();
+ if (val2.isConstructed())
+ ber.skip(val2.getLength());
+ }
+ else
+ digestEncryptionAlgorithmParams = null;
+
+ if (Configuration.DEBUG)
+ {
+ log.fine(" digestEncryptionAlgorithm params: ");
+ log.fine(Util.dumpString(digestEncryptionAlgorithmParams,
+ " digestEncryptionAlgorithm params: "));
+ }
+ val = ber.read();
+ if (val.getTag() != BER.OCTET_STRING)
+ throw new BEREncodingException("malformed EncryptedDigest");
+
+ encryptedDigest = (byte[]) val.getValue();
+ if (Configuration.DEBUG)
+ {
+ log.fine(" EncryptedDigest: ");
+ log.fine(Util.dumpString(encryptedDigest, " EncryptedDigest: "));
+ }
+ if (ber.peek() == 1)
+ unauthenticatedAttributes = ber.read().getEncoded();
+ else
+ unauthenticatedAttributes = null;
+
+ if (Configuration.DEBUG)
+ {
+ log.fine(" UnauthenticatedAttributes: ");
+ log.fine(Util.dumpString(unauthenticatedAttributes,
+ " UnauthenticatedAttributes: "));
+ }
+ if (ber.peek() == 0)
+ ber.read();
+ }
+
+ /**
+ * Constructs a new instance of <code>SignerInfo</code> given a designated
+ * set of fields.
+ *
+ * @param issuer the X.500 Principal name of the signer referenced by this
+ * instance.
+ * @param serialNumber the serial number of the certificate being used. Both
+ * this and the previous arguments are gleaned from the signer's
+ * certificate.
+ * @param digestAlgorithmOID the OID of the digest algorithm. When
+ * constructing the DigestAlgorithmIdentifier with this OID, the
+ * parameters part will be NULL.
+ * @param authenticatedAttributes the encoding of the set of authenticated
+ * attributes to use.
+ * @param digestEncryptionAlgorithmOID the OID of the digest encryption
+ * algorithm. When constructing the
+ * DigestEncryptionAlgorithmIdentifier with this OID, the parameters
+ * part will be NULL.
+ * @param encryptedDigest the encrypted hash generated with this signer's
+ * private key.
+ * @param unauthenticatedAttributes the encoding of the set of
+ * unauthencticated attributes.
+ */
+ public SignerInfo(X500Principal issuer, BigInteger serialNumber,
+ OID digestAlgorithmOID, byte[] authenticatedAttributes,
+ OID digestEncryptionAlgorithmOID,
+ byte[] encryptedDigest, byte[] unauthenticatedAttributes)
+ {
+ super();
+
+ this.version = BigInteger.ONE;
+ this.issuer = issuer;
+ this.serialNumber = serialNumber;
+ this.digestAlgorithmId = digestAlgorithmOID;
+ this.digestAlgorithmParams = null;
+ this.authenticatedAttributes = authenticatedAttributes;
+ this.digestEncryptionAlgorithmId = digestEncryptionAlgorithmOID;
+ this.digestEncryptionAlgorithmParams = null;
+ this.encryptedDigest = encryptedDigest;
+ this.unauthenticatedAttributes = unauthenticatedAttributes;
+ }
+
+ public BigInteger getVersion()
+ {
+ return version;
+ }
+
+ public BigInteger getSerialNumber()
+ {
+ return serialNumber;
+ }
+
+ public X500Principal getIssuer()
+ {
+ return issuer;
+ }
+
+ public OID getDigestAlgorithmId()
+ {
+ return digestAlgorithmId;
+ }
+
+ public byte[] getDigestAlgorithmParams()
+ {
+ return (digestAlgorithmParams != null
+ ? (byte[]) digestAlgorithmParams.clone()
+ : null);
+ }
+
+ public byte[] getAuthenticatedAttributes()
+ {
+ return (authenticatedAttributes != null
+ ? (byte[]) authenticatedAttributes.clone()
+ : null);
+ }
+
+ public OID getDigestEncryptionAlgorithmId()
+ {
+ return digestEncryptionAlgorithmId;
+ }
+
+ public byte[] getDigestEncryptionAlgorithmParams()
+ {
+ return (digestEncryptionAlgorithmParams != null
+ ? (byte[]) digestEncryptionAlgorithmParams.clone()
+ : null);
+ }
+
+ public byte[] getEncryptedDigest()
+ {
+ return (encryptedDigest != null ? (byte[]) encryptedDigest.clone() : null);
+ }
+
+ public byte[] getUnauthenticatedAttributes()
+ {
+ return (unauthenticatedAttributes != null
+ ? (byte[]) unauthenticatedAttributes.clone()
+ : null);
+ }
+
+ /**
+ * Writes to the designated output stream the DER encoding of the current
+ * contents of this instance.
+ *
+ * @param out the destination output stream.
+ * @throws IOException if an I/O related exception occurs during the process.
+ */
+ public void encode(OutputStream out) throws IOException
+ {
+ DERValue derVersion = new DERValue(DER.INTEGER, version);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
+ baos.write(issuer.getEncoded());
+ DERValue derSerialNumber = new DERValue(DER.INTEGER, serialNumber);
+ DERWriter.write(baos, derSerialNumber);
+ baos.flush();
+ byte[] b = baos.toByteArray();
+ DERValue derIssuerAndSerialNumber =
+ new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, b.length, b, null);
+
+ DERValue derDigestAlgorithmOID = new DERValue(DER.OBJECT_IDENTIFIER,
+ digestAlgorithmId);
+ ArrayList digestAlgorithmIdentifier = new ArrayList(1);
+ digestAlgorithmIdentifier.add(derDigestAlgorithmOID);
+ DERValue derDigestAlgorithmIdentifier =
+ new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, digestAlgorithmIdentifier);
+
+ DERValue derAuthenticatedAttributes;
+ if (authenticatedAttributes == null)
+ derAuthenticatedAttributes = new DERValue(DER.NULL, null);
+ else
+ derAuthenticatedAttributes = new DERValue(DER.CONSTRUCTED | DER.SET,
+ authenticatedAttributes);
+
+ DERValue derDigestEncryptionAlgorithmOID =
+ new DERValue(DER.OBJECT_IDENTIFIER, digestEncryptionAlgorithmId);
+ ArrayList digestEncryptionAlgorithmIdentifier = new ArrayList(1);
+ digestEncryptionAlgorithmIdentifier.add(derDigestEncryptionAlgorithmOID);
+ DERValue derDigestEncryptionAlgorithmIdentifier =
+ new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, digestEncryptionAlgorithmIdentifier);
+
+ DERValue derEncryptedDigest = new DERValue(DER.OCTET_STRING, encryptedDigest);
+
+ DERValue derUnauthenticatedAttributes;
+ if (unauthenticatedAttributes == null)
+ derUnauthenticatedAttributes = new DERValue(DER.NULL, null);
+ else
+ derUnauthenticatedAttributes = new DERValue(DER.CONSTRUCTED | DER.SET,
+ unauthenticatedAttributes);
+
+ ArrayList signerInfo = new ArrayList(5);
+ signerInfo.add(derVersion);
+ signerInfo.add(derIssuerAndSerialNumber);
+ signerInfo.add(derDigestAlgorithmIdentifier);
+ signerInfo.add(derDigestEncryptionAlgorithmIdentifier);
+ signerInfo.add(derEncryptedDigest);
+ DERValue derSignerInfo = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
+ signerInfo);
+ DERWriter.write(out, derSignerInfo);
+ }
+}
diff --git a/libjava/classpath/gnu/java/security/pkcs/package.html b/libjava/classpath/gnu/java/security/pkcs/package.html
new file mode 100644
index 000000000..60d658f8e
--- /dev/null
+++ b/libjava/classpath/gnu/java/security/pkcs/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in gnu.java.security.pkcs 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.pkcs</title></head>
+
+<body>
+<p></p>
+
+</body>
+</html>