1b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampackage org.bouncycastle.jce.provider;
2b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
3b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.io.BufferedInputStream;
4b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.io.ByteArrayInputStream;
5b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.io.ByteArrayOutputStream;
6b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.io.IOException;
7b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.io.InputStream;
8b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.io.OutputStreamWriter;
9b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.NoSuchProviderException;
10b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.cert.CertPath;
11b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.cert.Certificate;
12b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.cert.CertificateEncodingException;
13b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.cert.CertificateException;
14b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.cert.CertificateFactory;
15b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.security.cert.X509Certificate;
16b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.util.ArrayList;
17b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.util.Collections;
18b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.util.Enumeration;
19b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.util.Iterator;
20b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.util.List;
21b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.util.ListIterator;
22b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
23b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport javax.security.auth.x500.X500Principal;
24b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
25b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.ASN1Encodable;
26b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.ASN1EncodableVector;
27b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.ASN1InputStream;
28b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.ASN1Sequence;
29b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.DERInteger;
30b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.DERObject;
31b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.DERSequence;
32b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.DERSet;
33b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.pkcs.ContentInfo;
34b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
35b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.asn1.pkcs.SignedData;
36b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam// BEGIN android-removed
37b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam// import org.bouncycastle.openssl.PEMWriter;
38b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam// END android-removed
39b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
40b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam/**
41b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * CertPath implementation for X.509 certificates.
42b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * <br />
43b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam **/
44b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampublic  class PKIXCertPath
45b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    extends CertPath
46b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{
47b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    static final List certPathEncodings;
48b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
49b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    static
50b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
51b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        List encodings = new ArrayList();
52b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        encodings.add("PkiPath");
53b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        encodings.add("PEM");
54b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        encodings.add("PKCS7");
55b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        certPathEncodings = Collections.unmodifiableList(encodings);
56b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
57b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
58b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private List certificates;
59b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
60b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
61b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @param certs
62b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
63b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private List sortCerts(
64b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        List certs)
65b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
66b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (certs.size() < 2)
67b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
68b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            return certs;
69b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
70b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
71b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        X500Principal   issuer = ((X509Certificate)certs.get(0)).getIssuerX500Principal();
72b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        boolean         okay = true;
73b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
74b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        for (int i = 1; i != certs.size(); i++)
75b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
76b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            X509Certificate cert = (X509Certificate)certs.get(i);
77b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
78b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (issuer.equals(cert.getSubjectX500Principal()))
79b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
80b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                issuer = ((X509Certificate)certs.get(i)).getIssuerX500Principal();
81b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
82b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            else
83b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
84b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                okay = false;
85b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                break;
86b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
87b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
88b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
89b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (okay)
90b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
91b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            return certs;
92b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
93b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
94b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // find end-entity cert
95b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        List       retList = new ArrayList(certs.size());
96c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        List       orig = new ArrayList(certs);
97c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
98b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        for (int i = 0; i < certs.size(); i++)
99b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
100b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            X509Certificate cert = (X509Certificate)certs.get(i);
101b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            boolean         found = false;
102b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
103b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            X500Principal   subject = cert.getSubjectX500Principal();
104b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
105b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            for (int j = 0; j != certs.size(); j++)
106b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
107b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                X509Certificate c = (X509Certificate)certs.get(j);
108b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (c.getIssuerX500Principal().equals(subject))
109b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
110b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    found = true;
111b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    break;
112b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
113b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
114b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
115b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (!found)
116b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
117b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                retList.add(cert);
118b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                certs.remove(i);
119b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
120b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
121b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
122b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // can only have one end entity cert - something's wrong, give up.
123b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (retList.size() > 1)
124b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
125c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            return orig;
126b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
127b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
128b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        for (int i = 0; i != retList.size(); i++)
129b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
130b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            issuer = ((X509Certificate)retList.get(i)).getIssuerX500Principal();
131b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
132b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            for (int j = 0; j < certs.size(); j++)
133b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
134b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                X509Certificate c = (X509Certificate)certs.get(j);
135b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (issuer.equals(c.getSubjectX500Principal()))
136b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
137b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    retList.add(c);
138b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    certs.remove(j);
139b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    break;
140b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
141b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
142b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
143b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
144b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // make sure all certificates are accounted for.
145c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        if (certs.size() > 0)
146b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
147c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            return orig;
148b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
149b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
150b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return retList;
151b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
152b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
153b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    PKIXCertPath(List certificates)
154b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
155b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        super("X.509");
156b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        this.certificates = sortCerts(new ArrayList(certificates));
157b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
158b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
159b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
160b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * Creates a CertPath of the specified type.
161b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * This constructor is protected because most users should use
162b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * a CertificateFactory to create CertPaths.
163b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     **/
164b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    PKIXCertPath(
165b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        InputStream inStream,
166b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        String encoding)
167b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws CertificateException
168b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
169b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        super("X.509");
170b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        try
171b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
172b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (encoding.equalsIgnoreCase("PkiPath"))
173b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
174b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                ASN1InputStream derInStream = new ASN1InputStream(inStream);
175b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                DERObject derObject = derInStream.readObject();
176b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (!(derObject instanceof ASN1Sequence))
177b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
178b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    throw new CertificateException("input stream does not contain a ASN1 SEQUENCE while reading PkiPath encoded data to load CertPath");
179b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
180b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                Enumeration e = ((ASN1Sequence)derObject).getObjects();
181b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                certificates = new ArrayList();
1826e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                CertificateFactory certFactory = CertificateFactory.getInstance("X.509", BouncyCastleProvider.PROVIDER_NAME);
183b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                while (e.hasMoreElements())
184b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
185c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                    ASN1Encodable element = (ASN1Encodable)e.nextElement();
186c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                    byte[] encoded = element.getEncoded(ASN1Encodable.DER);
187c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                    certificates.add(0, certFactory.generateCertificate(
188c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                        new ByteArrayInputStream(encoded)));
189b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
190b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
191b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            else if (encoding.equalsIgnoreCase("PKCS7") || encoding.equalsIgnoreCase("PEM"))
192b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
193b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                inStream = new BufferedInputStream(inStream);
194b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                certificates = new ArrayList();
1956e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                CertificateFactory certFactory= CertificateFactory.getInstance("X.509", BouncyCastleProvider.PROVIDER_NAME);
196b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                Certificate cert;
197b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                while ((cert = certFactory.generateCertificate(inStream)) != null)
198b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
199b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    certificates.add(cert);
200b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
201b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
202b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            else
203b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
204b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                throw new CertificateException("unsupported encoding: " + encoding);
205b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
206b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
207b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        catch (IOException ex)
208b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
209b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new CertificateException("IOException throw while decoding CertPath:\n" + ex.toString());
210b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
211b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        catch (NoSuchProviderException ex)
212b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
213b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new CertificateException("BouncyCastle provider not found while trying to get a CertificateFactory:\n" + ex.toString());
214b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
215b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
216b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        this.certificates = sortCerts(certificates);
217b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
218b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
219b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
220b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * Returns an iteration of the encodings supported by this
221b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * certification path, with the default encoding
222b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * first. Attempts to modify the returned Iterator via its
223b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * remove method result in an UnsupportedOperationException.
224b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     *
225b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @return an Iterator over the names of the supported encodings (as Strings)
226b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     **/
227b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public Iterator getEncodings()
228b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
229b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return certPathEncodings.iterator();
230b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
231b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
232b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
233b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * Returns the encoded form of this certification path, using
234b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * the default encoding.
235b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     *
236b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @return the encoded bytes
237b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @exception CertificateEncodingException if an encoding error occurs
238b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     **/
239b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public byte[] getEncoded()
240b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws CertificateEncodingException
241b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
242b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Iterator iter = getEncodings();
243b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (iter.hasNext())
244b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
245b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            Object enc = iter.next();
246b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (enc instanceof String)
247b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
248b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            return getEncoded((String)enc);
249b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
250b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
251b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return null;
252b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
253b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
254b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
255b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * Returns the encoded form of this certification path, using
256b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * the specified encoding.
257b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     *
258b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @param encoding the name of the encoding to use
259b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @return the encoded bytes
260b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @exception CertificateEncodingException if an encoding error
261b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * occurs or the encoding requested is not supported
262b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     *
263b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     **/
264b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public byte[] getEncoded(String encoding)
265b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws CertificateEncodingException
266b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
267b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (encoding.equalsIgnoreCase("PkiPath"))
268b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
269b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            ASN1EncodableVector v = new ASN1EncodableVector();
270b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
271b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            ListIterator iter = certificates.listIterator(certificates.size());
272b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            while (iter.hasPrevious())
273b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
274b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                v.add(toASN1Object((X509Certificate)iter.previous()));
275b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
276b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
277b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            return toDEREncoded(new DERSequence(v));
278b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
279b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        else if (encoding.equalsIgnoreCase("PKCS7"))
280b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
281b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            ContentInfo encInfo = new ContentInfo(PKCSObjectIdentifiers.data, null);
282b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
283b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            ASN1EncodableVector v = new ASN1EncodableVector();
284b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            for (int i = 0; i != certificates.size(); i++)
285b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
286b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                v.add(toASN1Object((X509Certificate)certificates.get(i)));
287b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
288b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
289b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            SignedData  sd = new SignedData(
290b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                     new DERInteger(1),
291b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                     new DERSet(),
292b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                     encInfo,
293b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                     new DERSet(v),
294b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                     null,
295b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                     new DERSet());
296b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
297b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            return toDEREncoded(new ContentInfo(
298b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    PKCSObjectIdentifiers.signedData, sd));
299b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
300b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // BEGIN android-removed
301b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // else if (encoding.equalsIgnoreCase("PEM"))
302b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // {
303b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //     ByteArrayOutputStream bOut = new ByteArrayOutputStream();
304b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //     PEMWriter             pWrt = new PEMWriter(new OutputStreamWriter(bOut));
305b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
306b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //     try
307b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //     {
308b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //         for (int i = 0; i != certificates.size(); i++)
309b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //         {
310b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //             pWrt.writeObject(certificates.get(i));
311b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //         }
312b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
313b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //         pWrt.close();
314b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //     }
315b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //     catch (Exception e)
316b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //     {
317b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //         throw new CertificateEncodingException("can't encode certificate for PEM encoded path");
318b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //     }
319b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
320b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //     return bOut.toByteArray();
321b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // }
322b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // END android-removed
323b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        else
324b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
325b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new CertificateEncodingException("unsupported encoding: " + encoding);
326b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
327b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
328b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
329b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
330b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * Returns the list of certificates in this certification
331b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * path. The List returned must be immutable and thread-safe.
332b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     *
333b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @return an immutable List of Certificates (may be empty, but not null)
334b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     **/
335b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public List getCertificates()
336b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
337b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return Collections.unmodifiableList(new ArrayList(certificates));
338b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
339b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
340b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
341b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * Return a DERObject containing the encoded certificate.
342b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     *
343b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @param cert the X509Certificate object to be encoded
344b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     *
345b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @return the DERObject
346b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     **/
347b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private DERObject toASN1Object(
348b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        X509Certificate cert)
349b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws CertificateEncodingException
350b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
351b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        try
352b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
353b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            return new ASN1InputStream(cert.getEncoded()).readObject();
354b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
355b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        catch (Exception e)
356b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
357b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new CertificateEncodingException("Exception while encoding certificate: " + e.toString());
358b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
359b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
360b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
361b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private byte[] toDEREncoded(ASN1Encodable obj)
362b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws CertificateEncodingException
363b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
364b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        try
365b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
366c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            return obj.getEncoded(ASN1Encodable.DER);
367b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
368b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        catch (IOException e)
369b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
370c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            throw new CertificateEncodingException("Exception thrown: " + e);
371b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
372b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
373b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam}
374