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.HashSet;
9import java.util.Iterator;
10import java.util.List;
11import java.util.Set;
12
13import org.bouncycastle.asn1.ASN1Encodable;
14import org.bouncycastle.asn1.ASN1EncodableVector;
15import org.bouncycastle.asn1.ASN1InputStream;
16import org.bouncycastle.asn1.ASN1ObjectIdentifier;
17import org.bouncycastle.asn1.ASN1Set;
18import org.bouncycastle.asn1.ASN1TaggedObject;
19import org.bouncycastle.asn1.BEROctetStringGenerator;
20import org.bouncycastle.asn1.BERSet;
21import org.bouncycastle.asn1.DERNull;
22import org.bouncycastle.asn1.DERSet;
23import org.bouncycastle.asn1.DERTaggedObject;
24import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
25import org.bouncycastle.asn1.cms.ContentInfo;
26// BEGIN android-removed
27// import org.bouncycastle.asn1.cms.OtherRevocationInfoFormat;
28// import org.bouncycastle.asn1.ocsp.OCSPResponse;
29// import org.bouncycastle.asn1.ocsp.OCSPResponseStatus;
30// import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
31// import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
32// END android-removed
33import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
34import org.bouncycastle.cert.X509AttributeCertificateHolder;
35import org.bouncycastle.cert.X509CRLHolder;
36import org.bouncycastle.cert.X509CertificateHolder;
37import org.bouncycastle.operator.DigestCalculator;
38import org.bouncycastle.util.Store;
39import org.bouncycastle.util.Strings;
40import org.bouncycastle.util.io.Streams;
41import org.bouncycastle.util.io.TeeInputStream;
42import org.bouncycastle.util.io.TeeOutputStream;
43
44class CMSUtils
45{
46    private static final Set<String> des = new HashSet<String>();
47
48    static
49    {
50        des.add("DES");
51        des.add("DESEDE");
52        // BEGIN android-removed
53        // des.add(OIWObjectIdentifiers.desCBC.getId());
54        // des.add(PKCSObjectIdentifiers.des_EDE3_CBC.getId());
55        // des.add(PKCSObjectIdentifiers.des_EDE3_CBC.getId());
56        // des.add(PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId());
57        // END android-removed
58    }
59
60    static boolean isDES(String algorithmID)
61    {
62        String name = Strings.toUpperCase(algorithmID);
63
64        return des.contains(name);
65    }
66
67    static boolean isEquivalent(AlgorithmIdentifier algId1, AlgorithmIdentifier algId2)
68    {
69        if (algId1 == null || algId2 == null)
70        {
71            return false;
72        }
73
74        if (!algId1.getAlgorithm().equals(algId2.getAlgorithm()))
75        {
76            return false;
77        }
78
79        ASN1Encodable params1 = algId1.getParameters();
80        ASN1Encodable params2 = algId2.getParameters();
81        if (params1 != null)
82        {
83            return params1.equals(params2) || (params1.equals(DERNull.INSTANCE) && params2 == null);
84        }
85
86        return params2 == null || params2.equals(DERNull.INSTANCE);
87    }
88
89    static ContentInfo readContentInfo(
90        byte[] input)
91        throws CMSException
92    {
93        // enforce limit checking as from a byte array
94        return readContentInfo(new ASN1InputStream(input));
95    }
96
97    static ContentInfo readContentInfo(
98        InputStream input)
99        throws CMSException
100    {
101        // enforce some limit checking
102        return readContentInfo(new ASN1InputStream(input));
103    }
104
105    static List getCertificatesFromStore(Store certStore)
106        throws CMSException
107    {
108        List certs = new ArrayList();
109
110        try
111        {
112            for (Iterator it = certStore.getMatches(null).iterator(); it.hasNext();)
113            {
114                X509CertificateHolder c = (X509CertificateHolder)it.next();
115
116                certs.add(c.toASN1Structure());
117            }
118
119            return certs;
120        }
121        catch (ClassCastException e)
122        {
123            throw new CMSException("error processing certs", e);
124        }
125    }
126
127    static List getAttributeCertificatesFromStore(Store attrStore)
128        throws CMSException
129    {
130        List certs = new ArrayList();
131
132        try
133        {
134            for (Iterator it = attrStore.getMatches(null).iterator(); it.hasNext();)
135            {
136                X509AttributeCertificateHolder attrCert = (X509AttributeCertificateHolder)it.next();
137
138                certs.add(new DERTaggedObject(false, 2, attrCert.toASN1Structure()));
139            }
140
141            return certs;
142        }
143        catch (ClassCastException e)
144        {
145            throw new CMSException("error processing certs", e);
146        }
147    }
148
149
150    static List getCRLsFromStore(Store crlStore)
151        throws CMSException
152    {
153        List crls = new ArrayList();
154
155        try
156        {
157            for (Iterator it = crlStore.getMatches(null).iterator(); it.hasNext();)
158            {
159                Object rev = it.next();
160
161                if (rev instanceof X509CRLHolder)
162                {
163                    X509CRLHolder c = (X509CRLHolder)rev;
164
165                    crls.add(c.toASN1Structure());
166                }
167                // BEGIN android-removed
168                // else if (rev instanceof OtherRevocationInfoFormat)
169                // {
170                //     OtherRevocationInfoFormat infoFormat = OtherRevocationInfoFormat.getInstance(rev);
171                //
172                //     validateInfoFormat(infoFormat);
173                //
174                //     crls.add(new DERTaggedObject(false, 1, infoFormat));
175                // }
176                // END android-removed
177                else if (rev instanceof ASN1TaggedObject)
178                {
179                    crls.add(rev);
180                }
181            }
182
183            return crls;
184        }
185        catch (ClassCastException e)
186        {
187            throw new CMSException("error processing certs", e);
188        }
189    }
190
191    // BEGIN android-removed
192    // private static void validateInfoFormat(OtherRevocationInfoFormat infoFormat)
193    // {
194    //     if (CMSObjectIdentifiers.id_ri_ocsp_response.equals(infoFormat.getInfoFormat()))
195    //     {
196    //         OCSPResponse resp = OCSPResponse.getInstance(infoFormat.getInfo());
197    //
198    //         if (resp.getResponseStatus().getValue().intValue() != OCSPResponseStatus.SUCCESSFUL)
199    //         {
200    //             throw new IllegalArgumentException("cannot add unsuccessful OCSP response to CMS SignedData");
201    //         }
202    //     }
203    // }
204    //
205    // static Collection getOthersFromStore(ASN1ObjectIdentifier otherRevocationInfoFormat, Store otherRevocationInfos)
206    // {
207    //     List others = new ArrayList();
208    //
209    //     for (Iterator it = otherRevocationInfos.getMatches(null).iterator(); it.hasNext();)
210    //     {
211    //         ASN1Encodable info = (ASN1Encodable)it.next();
212    //         OtherRevocationInfoFormat infoFormat = new OtherRevocationInfoFormat(otherRevocationInfoFormat, info);
213    //         validateInfoFormat(infoFormat);
214    //
215    //         others.add(new DERTaggedObject(false, 1, infoFormat));
216    //     }
217    //
218    //     return others;
219    // }
220    // END android-removed
221
222    static ASN1Set createBerSetFromList(List derObjects)
223    {
224        ASN1EncodableVector v = new ASN1EncodableVector();
225
226        for (Iterator it = derObjects.iterator(); it.hasNext();)
227        {
228            v.add((ASN1Encodable)it.next());
229        }
230
231        return new BERSet(v);
232    }
233
234    static ASN1Set createDerSetFromList(List derObjects)
235    {
236        ASN1EncodableVector v = new ASN1EncodableVector();
237
238        for (Iterator it = derObjects.iterator(); it.hasNext();)
239        {
240            v.add((ASN1Encodable)it.next());
241        }
242
243        return new DERSet(v);
244    }
245
246    static OutputStream createBEROctetOutputStream(OutputStream s,
247            int tagNo, boolean isExplicit, int bufferSize) throws IOException
248    {
249        BEROctetStringGenerator octGen = new BEROctetStringGenerator(s, tagNo, isExplicit);
250
251        if (bufferSize != 0)
252        {
253            return octGen.getOctetOutputStream(new byte[bufferSize]);
254        }
255
256        return octGen.getOctetOutputStream();
257    }
258
259    private static ContentInfo readContentInfo(
260        ASN1InputStream in)
261        throws CMSException
262    {
263        try
264        {
265            return ContentInfo.getInstance(in.readObject());
266        }
267        catch (IOException e)
268        {
269            throw new CMSException("IOException reading content.", e);
270        }
271        catch (ClassCastException e)
272        {
273            throw new CMSException("Malformed content.", e);
274        }
275        catch (IllegalArgumentException e)
276        {
277            throw new CMSException("Malformed content.", e);
278        }
279    }
280
281    public static byte[] streamToByteArray(
282        InputStream in)
283        throws IOException
284    {
285        return Streams.readAll(in);
286    }
287
288    public static byte[] streamToByteArray(
289        InputStream in,
290        int         limit)
291        throws IOException
292    {
293        return Streams.readAllLimited(in, limit);
294    }
295
296    static InputStream attachDigestsToInputStream(Collection digests, InputStream s)
297    {
298        InputStream result = s;
299        Iterator it = digests.iterator();
300        while (it.hasNext())
301        {
302            DigestCalculator digest = (DigestCalculator)it.next();
303            result = new TeeInputStream(result, digest.getOutputStream());
304        }
305        return result;
306    }
307
308    static OutputStream attachSignersToOutputStream(Collection signers, OutputStream s)
309    {
310        OutputStream result = s;
311        Iterator it = signers.iterator();
312        while (it.hasNext())
313        {
314            SignerInfoGenerator signerGen = (SignerInfoGenerator)it.next();
315            result = getSafeTeeOutputStream(result, signerGen.getCalculatingOutputStream());
316        }
317        return result;
318    }
319
320    static OutputStream getSafeOutputStream(OutputStream s)
321    {
322        return s == null ? new NullOutputStream() : s;
323    }
324
325    static OutputStream getSafeTeeOutputStream(OutputStream s1,
326            OutputStream s2)
327    {
328        return s1 == null ? getSafeOutputStream(s2)
329                : s2 == null ? getSafeOutputStream(s1) : new TeeOutputStream(
330                        s1, s2);
331    }
332}
333