1package org.bouncycastle.cms;
2
3import java.io.IOException;
4import java.io.InputStream;
5import java.io.OutputStream;
6import java.util.ArrayList;
7import java.util.Collection;
8import java.util.Iterator;
9import java.util.List;
10
11import org.bouncycastle.asn1.ASN1Encodable;
12import org.bouncycastle.asn1.ASN1EncodableVector;
13import org.bouncycastle.asn1.ASN1InputStream;
14import org.bouncycastle.asn1.ASN1ObjectIdentifier;
15import org.bouncycastle.asn1.ASN1Set;
16import org.bouncycastle.asn1.BEROctetStringGenerator;
17import org.bouncycastle.asn1.BERSet;
18import org.bouncycastle.asn1.DERSet;
19import org.bouncycastle.asn1.DERTaggedObject;
20import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
21import org.bouncycastle.asn1.cms.ContentInfo;
22// BEGIN android-removed
23// import org.bouncycastle.asn1.cms.OtherRevocationInfoFormat;
24// import org.bouncycastle.asn1.ocsp.OCSPResponse;
25// import org.bouncycastle.asn1.ocsp.OCSPResponseStatus;
26// END android-removed
27import org.bouncycastle.cert.X509AttributeCertificateHolder;
28import org.bouncycastle.cert.X509CRLHolder;
29import org.bouncycastle.cert.X509CertificateHolder;
30import org.bouncycastle.operator.DigestCalculator;
31import org.bouncycastle.util.Store;
32import org.bouncycastle.util.io.Streams;
33import org.bouncycastle.util.io.TeeInputStream;
34import org.bouncycastle.util.io.TeeOutputStream;
35
36class CMSUtils
37{
38    static ContentInfo readContentInfo(
39        byte[] input)
40        throws CMSException
41    {
42        // enforce limit checking as from a byte array
43        return readContentInfo(new ASN1InputStream(input));
44    }
45
46    static ContentInfo readContentInfo(
47        InputStream input)
48        throws CMSException
49    {
50        // enforce some limit checking
51        return readContentInfo(new ASN1InputStream(input));
52    }
53
54    static List getCertificatesFromStore(Store certStore)
55        throws CMSException
56    {
57        List certs = new ArrayList();
58
59        try
60        {
61            for (Iterator it = certStore.getMatches(null).iterator(); it.hasNext();)
62            {
63                X509CertificateHolder c = (X509CertificateHolder)it.next();
64
65                certs.add(c.toASN1Structure());
66            }
67
68            return certs;
69        }
70        catch (ClassCastException e)
71        {
72            throw new CMSException("error processing certs", e);
73        }
74    }
75
76    static List getAttributeCertificatesFromStore(Store attrStore)
77        throws CMSException
78    {
79        List certs = new ArrayList();
80
81        try
82        {
83            for (Iterator it = attrStore.getMatches(null).iterator(); it.hasNext();)
84            {
85                X509AttributeCertificateHolder attrCert = (X509AttributeCertificateHolder)it.next();
86
87                certs.add(new DERTaggedObject(false, 2, attrCert.toASN1Structure()));
88            }
89
90            return certs;
91        }
92        catch (ClassCastException e)
93        {
94            throw new CMSException("error processing certs", e);
95        }
96    }
97
98
99    static List getCRLsFromStore(Store crlStore)
100        throws CMSException
101    {
102        List certs = new ArrayList();
103
104        try
105        {
106            for (Iterator it = crlStore.getMatches(null).iterator(); it.hasNext();)
107            {
108                X509CRLHolder c = (X509CRLHolder)it.next();
109
110                certs.add(c.toASN1Structure());
111            }
112
113            return certs;
114        }
115        catch (ClassCastException e)
116        {
117            throw new CMSException("error processing certs", e);
118        }
119    }
120
121    // BEGIN android-removed
122    // static Collection getOthersFromStore(ASN1ObjectIdentifier otherRevocationInfoFormat, Store otherRevocationInfos)
123    // {
124    //     List others = new ArrayList();
125    //
126    //     for (Iterator it = otherRevocationInfos.getMatches(null).iterator(); it.hasNext();)
127    //     {
128    //         ASN1Encodable info = (ASN1Encodable)it.next();
129    //
130    //         if (CMSObjectIdentifiers.id_ri_ocsp_response.equals(otherRevocationInfoFormat))
131    //         {
132    //             OCSPResponse resp = OCSPResponse.getInstance(info);
133    //
134    //             if (resp.getResponseStatus().getValue().intValue() != OCSPResponseStatus.SUCCESSFUL)
135    //             {
136    //                 throw new IllegalArgumentException("cannot add unsuccessful OCSP response to CMS SignedData");
137    //             }
138    //         }
139    //
140    //         others.add(new DERTaggedObject(false, 1, new OtherRevocationInfoFormat(otherRevocationInfoFormat, info)));
141    //     }
142    //
143    //     return others;
144    // }
145    // END android-removed
146
147    static ASN1Set createBerSetFromList(List derObjects)
148    {
149        ASN1EncodableVector v = new ASN1EncodableVector();
150
151        for (Iterator it = derObjects.iterator(); it.hasNext();)
152        {
153            v.add((ASN1Encodable)it.next());
154        }
155
156        return new BERSet(v);
157    }
158
159    static ASN1Set createDerSetFromList(List derObjects)
160    {
161        ASN1EncodableVector v = new ASN1EncodableVector();
162
163        for (Iterator it = derObjects.iterator(); it.hasNext();)
164        {
165            v.add((ASN1Encodable)it.next());
166        }
167
168        return new DERSet(v);
169    }
170
171    static OutputStream createBEROctetOutputStream(OutputStream s,
172            int tagNo, boolean isExplicit, int bufferSize) throws IOException
173    {
174        BEROctetStringGenerator octGen = new BEROctetStringGenerator(s, tagNo, isExplicit);
175
176        if (bufferSize != 0)
177        {
178            return octGen.getOctetOutputStream(new byte[bufferSize]);
179        }
180
181        return octGen.getOctetOutputStream();
182    }
183
184    private static ContentInfo readContentInfo(
185        ASN1InputStream in)
186        throws CMSException
187    {
188        try
189        {
190            return ContentInfo.getInstance(in.readObject());
191        }
192        catch (IOException e)
193        {
194            throw new CMSException("IOException reading content.", e);
195        }
196        catch (ClassCastException e)
197        {
198            throw new CMSException("Malformed content.", e);
199        }
200        catch (IllegalArgumentException e)
201        {
202            throw new CMSException("Malformed content.", e);
203        }
204    }
205
206    public static byte[] streamToByteArray(
207        InputStream in)
208        throws IOException
209    {
210        return Streams.readAll(in);
211    }
212
213    public static byte[] streamToByteArray(
214        InputStream in,
215        int         limit)
216        throws IOException
217    {
218        return Streams.readAllLimited(in, limit);
219    }
220
221    static InputStream attachDigestsToInputStream(Collection digests, InputStream s)
222    {
223        InputStream result = s;
224        Iterator it = digests.iterator();
225        while (it.hasNext())
226        {
227            DigestCalculator digest = (DigestCalculator)it.next();
228            result = new TeeInputStream(result, digest.getOutputStream());
229        }
230        return result;
231    }
232
233    static OutputStream attachSignersToOutputStream(Collection signers, OutputStream s)
234    {
235        OutputStream result = s;
236        Iterator it = signers.iterator();
237        while (it.hasNext())
238        {
239            SignerInfoGenerator signerGen = (SignerInfoGenerator)it.next();
240            result = getSafeTeeOutputStream(result, signerGen.getCalculatingOutputStream());
241        }
242        return result;
243    }
244
245    static OutputStream getSafeOutputStream(OutputStream s)
246    {
247        return s == null ? new NullOutputStream() : s;
248    }
249
250    static OutputStream getSafeTeeOutputStream(OutputStream s1,
251            OutputStream s2)
252    {
253        return s1 == null ? getSafeOutputStream(s2)
254                : s2 == null ? getSafeOutputStream(s1) : new TeeOutputStream(
255                        s1, s2);
256    }
257}
258